Make your own free website on
5.8. Character-wise and Line-wise I/O

Basically, the built-in REXX library offers two strategies of
reading and writing streams: line-wise and character-wise. When
reading line-wise, the underlying storage method of the stream
must contain information which describes where each line starts
and ends.

Some file systems store this information as one or more special
characters; while others structure the file in a number of
records; each containing a single line.  This introduces a
slightly subtle point; even though a stream foo returns the same
data when read by LINEIN()on two different machines; the data read
from foo may differ between the same two machines when the stream
is read by CHARIN(), and vice versa. This is so because the end-of-
line markers can vary between the two operating systems.

Example: Character-wise handling of EOL

Suppose a text file contains the following three lines (ASCII
character set is assumed):


and you first read it line-wise and then character-wise. Assume
the following program:

     file = ‘DATAFILE’
     foo = ‘’
     do i=1 while chars(file)>0
          foo = foo || c2x(charin(file))‘ ’
     say foo

When the file is read line-wise, the output is identical on all
machines, i.e. the three lines shown above. However, the character-
wise reading will be dependent on your operating system and its
file system, thus, the output might e.g. be any of:

     66 69 72 73 74 73 65 6F 63 6E 64 74 68 69 72 64 66 69 72 73
     74 0A
     66 69 72 73 74 0A
     73 65 6F 63 6E 64 0A
     74 68 69 72 64 0A
     66 69 72 73 74 0D 0A
     73 65 6F 63 6E 64 0D 0A
     74 68 69 72 64 0D 0A

If the machine uses records to store the lines, the first one may
be the result; here, only the data in the lines of the file is
returned.  Note that the boxes in the output are put around the
data generated by the actual line contents. What is outside the
boxes is generated by the end-of-line character sequences.

The second output line is typical for Unix machines. They use the
newline ASCII character as line separator, and that character is
read immediately after each line. The last line is typical for MS-
DOS, where the line separator character sequence is a carriage
return following by a newline (ASCII ‘0D’x and ‘0A’x).

For maximum portability, the line-wise built-in functions
(LINEIN(), LINEOUT() and LINES()) should only be used for line-
wise streams. And the character-wise built-in functions (CHARIN(),
CHAROUT() and CHARS()) should only be used for character-wise
data. You should in general be very careful when mixing character-
and line-wise data in a single stream; it does work, but may
easily lead to portability problems.

The difference between character- and line-wise streams are
roughly equivalent to the difference between binary and text
streams, but the two concepts are not totally equivalent. In a
binary file, the data read is the actual data stored in the file,
while in a text file, the character sequences used for denoting
end-of-line and end-of-file markers may be translated to actions
or other characters during reading.

The end-of-file marker may be differently implemented on different
systems. On some systems, this marker is only implicitly present
at the end-of-file—-which is calculated from the file size (e.g.
Unix). Other systems may put a character signifying end-of-file at
the end (or even in the middle) of the file (e.g. <Ctrl-Z> for MS-
DOS).  These concepts vary between operating systems, interpreters
should handle each concept according to the customs of the
operating system.  Check the implementation-specific documentation
for further information. In any case, if the interpreter treats a
particular character as end-of-file, then it only gives special
treatment to this character during line-wise operations. During
character-wise operations, no characters have special meanings.