PxPLUS and ASCII-text files
PxPLUS has 9 ways to write to string files.
There are 3 ways to OPEN the file:
- OPEN (1) FILE$
- OPEN (1,ISZ=1) FILE$
- OPEN(1,ISZ=n)FILE$, where n>1.
And there are 3 commands to fill it:
- PRINT
- WRITE
- WRITE RECORD
It depends on the combination you use, what PxPLUS
will append to each record.
|
OPEN (1) |
OPEN (1,ISZ=1) |
OPEN (1,ISZ=n) n>1 |
PRINT |
0D0A |
0D0A |
0D0A000000... |
WRITE |
8A0D0A |
8A |
8A0000000000... |
WRITE RECORD |
0D0A |
Nothing |
000000... till LEN=n |
So if you want that nothing gets appended to your data, you have to OPEN
your file with option ISZ=1 and use WRITE RECORD to write the
data.
PxPLUS does a pre-scan on the first line of a
serial file. When a character is found outside the range of a " " (space)
through a "~", PxPLUS considers the file a binary file and then the rules of
'OPEN (1,ISZ=1)' apply.
You will have to LOCK the file before you can
write to the file.
PxPLUS will handle the file in a record oriented way.
The IND() function returns the current record number.
PxPLUS will always append $0D0A$ (1)to
the end of a record.
In case of a WRITE verb, an extra field separator ($8A$) (2) will be
appended, before the record separator ($0D0A$)
A 'READ RECORD' scans the data in the file for a
$0D0A$ byte combination.
A 'READ' implies a 'READ RECORD'. The data from the 'READ RECORD' is then parsed
into the variables, where $8A$ acts as fieldseparator.
A 'READ (1,IND=n)' reads the n+1th record.
1 Record Separator
If running under Windows, the record separator is $0D0A$
When running under UNIX, the record separator is $0A$
In my examples, $0D0A$ is used.
2 Field Separator
The default field separator is $8A$, but can be changed to something else with
the 'FS' parameter.
Opening a file with ',ISZ=1', opens the file in
BINARY mode, even if you open a KEYED file with ',ISZ=1', PxPLUS will treat
the file as if it was a binary file.
For compatibility reasons with other Business Basics, 'ISZ= -1' is allowed.
This mode of OPEN, implies a LOCK to the file.
PxPLUS will handle the file in a byte-oriented way.
The IND() function returns the current byte count.
PRINT X$ writes X$+$0D0A$
WRITE X$ writes X$+$8A$
WRITE RECORD X$ writes X$ and adds nothing to the variable, but if the variable
is empty, a $00$ byte will be added.
Normally you will read the file with READ
RECORD(1,SIZ=nnn)X$
Otherwise, 'SIZ=1' is taken.
A 'READ(1,IND=n)' reads the n+1th byte.
Watch out for this kind of file access.
Always test your application if you use this kind of approach
A 'PRINT' writes the variable(s) to the file.
Each PRINT is terminated by $0D0A$.
Consecutive PRINTs can be performed. No field separator between two fields.
When the n bytes are reached, an ERROR #1 is generated.
When the n bytes are not reached, the rest of the n bytes are filled with $00$
A 'WRITE' writes the variable(s) to the file. A field separator ($8A$) will be
appended after each field. The rest of the n bytes will be filled with $00$.
A 'WRITE RECORD' writes the data to the file. The rest of the n bytes will be
filled with $00$
A 'READ' implies a READ RECORD of n bytes. The
data found will be parsed into variables.
A 'READ RECORD' reads n bytes (n = specified by OPEN)
A 'READ RECORD (1,SIZ=x) will read x bytes.
- Tip: Do not mix PRINT, WRITE, and WRITE RECORD to fill a file.
Summary
- If you want to fill a serial file with the purpose to merge back the
data:
WRITE PROCEDURE |
READ PROCEDURE |
SERIAL F$
OPEN LOCK (1) F$
PRINT (1)"10 REM"
PRINT (1)"20 BEGIN"
PRINT (1)"30 FOR I=1 to 10"
PRINT ...
PRINT (1)"9999 END
|
CLOSE (1)
OPEN (1)F$
MERGE (1)
|
- If you want to have full control:
Fe. : You have to prepare a file for someone
else to read.
They impose a certain format: the record must be 128 chars long, plus a
'TAB' (hex09) as separator.
WRITE PROCEDURE |
READ PROCEDURE |
SERIAL F$
OPEN (1,isz=1) F$
DIM X$(128)
X$(1)=SOME_CODE$
X$(25)=OTHER_STUFF$
...
X$=X$+$09$
WRITE RECORD (1)X$
...
|
OPEN(1,isz=1)F$
GET:
READ(1,siz=129,end=DONE)X$
GOTO GET
DONE:
|
- If you want to write variables to a serial file with the purpose to read
them back in:
WRITE PROCEDURE |
READ PROCEDURE |
SERIAL F$
OPEN LOCK (1) F$
PUT:
A$= ... , B$= ... , C$= ...
WRITE (1)A$,B$,C$
GOTO PUT
|
OPEN (1) F$
GET:
READ(1,end=DONE)X$,Y$,Z$
GOTO GET
DONE:
|
Sample program
0010 BEGIN ; PRINT 'CS','SB'
0020 FOR I=1 TO 2
0030 LET F$="c:\tmp\erase.me"; ERASE F$,ERR=*PROCEED; SERIAL F$
0050 !
0060 IF I=1 THEN OPEN LOCK (1)F$; PRINT "OPEN (1) "
0070 IF I=2 THEN OPEN LOCK (1,ISZ=1)F$; PRINT "OPEN(1,ISZ=1)"
0080 !
0090 PRINT (1)"111"
0100 WRITE (1)"222"
0110 WRITE RECORD (1)"333"
0130 PRINT (1)"444"
0140 WRITE (1)"555"
0150 WRITE RECORD (1)"666"
0160 !
0170 CLOSE (1); OPEN (1,ISZ=1) F$
0180 READ RECORD (1,SIZ=-1000) X$
0190 PRINT 'LF',"Binary file contents: ",'LF','LF','SF',HTA(X$),
0200 !
0330 CLOSE (1)
0331 PRINT 'SB','LF'
0340 NEXT I
|