The Channel class / Usage |
When the channel is open, use the read()/write() methods to read and write data records where field values are separated by a delimiter defined by setDelimiter().
The input or output stream is text data where each line contains the string representation of a record. Field values are separated by the delimiter character defined.
For example, a formatted text file can look like this, when using a default pipe (|) delimiter:
8712|David|Cosneski|24-12-1978| 3422|Frank|Zapinetti|13-04-1968| 323|Mark|Kelson|03-10-1988|
In the serialized data, empty fields (||) have a length of zero and are considered as NULL.
To read the above formatted data, the code could be:
MAIN DEFINE ch base.Channel DEFINE custinfo RECORD cust_num INTEGER, cust_fname VARCHAR(40), cust_lname VARCHAR(40), cust_bdate DATE END RECORD LET ch = base.Channel.create() CALL ch.setDelimiter("|") CALL ch.openFile("custinfo.txt","r") WHILE ch.read([custinfo.*]) DISPLAY custinfo.* END WHILE CALL ch.close() END MAIN
The backslash \ is the escape character: When writing data with write(), special characters like the backslash, line-feed or the delimiter character will be escaped. When reading data with read(), any escaped \char character will be converted to char.
The next code writes a single field value where the character string contains a backslash, the pipe delimiter and a line-feed character. The backslash is also the escape character for string literals, therefore we need to double the backslash to get a backslash in the string, while the line-feed character (<lf>) is represented by backslash-n (\n) in string literals:
CALL ch.setDelimiter("|") CALL ch.write("aaa\\bbb|ccc\nddd") -- [aaa<bs>bbb|ccc<lf>ddd]
This code will produce the following text file:
aaa\\bbb\|ccc\ ddd|
When reading such a line back into memory with the read() method, all escaped characters are converted back to the single character. In this example, \\ becomes \, \| becomes | and \<lf> becomes <lf>.
When using the read()/write() methods, the escaped line-feed (LF, \n) characters are written as BS + LF to the output, and when reading with read(), BS + LF are detected and interpreted, to be restored as if the value was assigned by a LET instruction, with the same string used in the write() function.
If you want to write a LF as part of a value, the string must contain the backslash and line-feed as two independent characters. You need to escape the backslash when you write the string constant in the .4gl source file.
CALL ch.setDelimiter("|") CALL ch.write("aaa\\\nbbb") -- [aaa<bs><lf>bbb] CALL ch.write("ccc\nddd") -- [aaa<lf>bbb]
would generate the following output:
aaa\ bbb| ccc| ddd|
where the first two lines contain data for the same line, in the meaning of a Channel record.
When you read these lines back with a read() call, you get the following strings in memory:
Read 1: aaa<bs><lf>bbb Read 2: ccc Read 3: ddd
These reads would correspond to the following assignments when using string constants:
LET s = "aaa\\\nbbb" LET s = "ccc" LET s = "ddd"
CALL ch.setDelimiter("CSV")
This CSV format is similar to the standard channel format, with the following differences: