I wanted to read in a (large) "text" file of 8-bit numbers (eg. 0-255), space delimited, and then process the data and output it as a binary file... yes, I know... they're all binary files. I mean, I wanted the values output to file to not be output as characters/text, but as actual single-byte values of what each value is for 0-255. For example, VS Code would see it as a "binary" file and load it into the Hex Editor*.
There are many internet references to "input" (loading) binary data into Basic, but not so much about the "output". ChatGPT4 suggests it's just not possible . Sure there's a brief overview of (confusing) codes in various website copies of the C64 "OPEN" command, and PRINT# command info - but not lots of details. To be fair, going back to the original manuals did have a bit more information on numbers being "spaced", but it focuses more on "string" examples and not "number values".
Anyway, I couldn't easily find any reference to the output "characters" and how it all works. I tried outputting the number values, hex values, strings, with mixed results - and then finally saw a reference to CHR$(value). The CHR$ output achieved what I needed, although it wasn't obvious to me Why at the time? Other than the ASCII code created will output a "value" outside the text range of characters (more easily). It seems more that the PRINT# command respects this converted value more than other interpretations of "values". As CHR$ output handles 0-255, this will trigger other applications to see the file as "binary" over an assumed "text" file (if I have numbers outside the text range).
For the beginner still reading... I found that the PRINT#, command was better at outputting from actual "string/character" values or variables, than number variables (although whilst writing this, I didn't try integer% variables?). The output of number data is converted to strings (just like the onscreen "PRINT" I assume), which is where it goes wrong. There is the classic "spaces" surrounding a number to screen. The "number/integer" is converted to a string as the actual representation of the value. So, instead of outputting the number variable value of 65 (as a single byte value), which might be interpreted by other applications as the letter A (in the file), it outputs : SPACE-SIX-FIVE-SPACE. These are stored as 4 characters of ASCII values 32-54-53-32 (or HEX 20-36-35-20)... which represent the "6" & "5" and not the required "A" or ASCII 65 (or HEX 41)... in a single byte. It appears there are different outputs depending on different methods of value storage and what Value you're working with. I don't know if there are other characters beyond "0" which are treated differently, I just wanted 1 method that worked for all numbers.
The following code might help in testing your own character output needs, or at least visually explains some variations I tested.
10 OPEN 1,8,2,"EXAMPLE,S,W"
15 A$="A":A=65
16 B$="0":B=0
17 C$="#":C=35
20 REM WRITES VARIATIONS OF VALUES/STRINGS/VARIABLES TO OUTPUT FILE
29 REM ----------------------------------- HEX codes
30 PRINT#1,A$ : REM Y = 41
31 PRINT#1,"A" : REM Y = 41
32 PRINT#1,A : REM N = 20 36 35 20
33 PRINT#1,65 : REM N = 20 36 35 20
34 PRINT#1,HEX$(ASC("A")) : REM N = 34 31
35 PRINT#1,CHR$(ASC(A$)) : REM Y = 41
36 PRINT#1,CHR$(ASC("A")) :REM Y = 41
37 PRINT#1,CHR$(A) : REM Y = 41
38 PRINT#1,CHR$(65) : REM Y = 41
39 REM ----------------------------------- HEX codes
40 PRINT#1,B$ :REM N = 30
41 PRINT#1,"0" : REM N = 30
42 PRINT#1,B : REM N = 20 30 20
43 PRINT#1,0 N = 20 30 20
44 PRINT#1,HEX$(ASC("0")) : REM N = 33 30
45 PRINT#1,CHR$(ASC(B$)) : REM N = 30
46 PRINT#1,CHR$(ASC("0")) :REM N = 30
47 PRINT#1,CHR$(B) :REM Y = 0
48 PRINT#1,CHR$(0) : REM Y = 0
49 REM ----------------------------------- HEX codes
50 PRINT#1,C$ : REM Y = 23
51 PRINT#1,"#" : REM Y = 23
52 PRINT#1,C : REM N = 20 33 35 20
53 PRINT#1,35 : REM N = 20 33 35 20
54 PRINT#1,HEX$(ASC("#")) : REM N = 32 33
55 PRINT#1,CHR$(ASC(C$)) : REM Y = 23
56 PRINT#1,CHR$(ASC("#")) : REM Y = 23
57 PRINT#1,CHR$(C) : REM Y = 23
58 PRINT#1,CHR$(35) : REM Y = 23
59 REM --------------------------------
60 CLOSE 1