[MD+F Web AK: Web animations, imagemaps, patterns, and more for use with any paint program. (click here)]

The REXX Files- by Dr. Dirk Terrell


This month, let's look at some of the REXX input and output functions. If you are learning REXX, it won't be long before you want to create and process files. REXX offers a couple of ways of reading and writing data files. One is by processing a set number of characters at a time and the other is processing one line of text at a time.

Functions that deal with characters (bytes) rather than lines begin with "CHAR" such as CHARS, CHARIN, and CHAROUT. The CHARS function returns the number of characters that can be read from a file. If you have not yet performed any operations on the file, it will return the size of the file in bytes. If you have already performed read operations on the file, it will tell you how many characters are left. To use CHARS simply pass the file name as a parameter like this:

Number_of_Characters=CHARS("c:\config.sys")

CHARIN and CHAROUT are used to read and write characters. CHARIN uses the following syntax:

data=CHARIN(file,start,number)

where data holds the data read in, start is the starting position in the file to perform the read operation, and number is the number of characters to read. If you do not specify file, then standard input will be used (i.e., the program will wait for the user to type in data). If you do not specify start, the next available character is the default starting point. If number is larger than the number of available bytes, CHARIN will read the remaining characters. If you want to read an entire file into memory, you can combine the CHARS and CHARIN functions like this:

data=CHARIN(file,1,CHARS(file))

The CHAROUT function writes characters to a file:

rc=CHAROUT(file,string,start)

Again, file is the file to write data to (standard output, the screen, is the default), start is the character position in the file to begin writing, and string is a string containing the characters to write. The function will return the number of bytes that are left to be written. Normally it will be zero unless some sort of problem occurred.

Functions that deal with line input and output begin with "LINE". These functions read or write lines of data delimited by the end-of-line sequence which is a carriage return and linefeed pair (ASCII 13 and ASCII 10). If you need to read one line at a time from a file, this is your function. Use it as follows:

data=Linein(file,line,count)

where file is the file name. The parameters line and count seem to have limited functions. Setting line to one will move the pointer back to the first line in the file (like a rewind), and setting count to zero will cause LINEIN not to actually read anything. Setting count to numbers greater than one will not cause it to read multiple lines though. Most of the time, you will probably use LINEIN by specifying just the file name.

LINEOUT will write a line of data to a file. The calling form is:

rc=LINEOUT(file,string,line) where file is the file name, string is the string to be written, and line can be set to one if you want to begin writing at the beginning of a file. One thing to note about this function is that it appends lines to a file if it already exists. If you want to overwrite a file, you must explicitly delete it (using SysFileDelete from the REXXUTIL library) before using LINEOUT.

The LINES function is somewhat similar to the CHARS function. It will return a one or a zero depending on whether or not there are lines left to be read in from a file. For example, to read in all the lines of a file, use this code:

/* Count the number of lines in a file
   and store them in a stem
*/
Parse Arg File
i=1
time1=Time("E")
time1=Time("R")
Do While LINES(file)
   Data.i=LINEIN(file)
   i=i+1
End
time2=Time("E")
ET=Time2-Time1
Say "It took" ET "seconds to read the file."
Say "There were" i-1 "lines in" file
Exit
Note the use of the STREAM function to explicitly close the file when we are finished reading the data. Failure to close files is a common source of problems for beginners. There are a limited number of file handles available on your system, and you will run out of them if you fail to close files when you are finished reading from or writing to them. If you are having a problem with a REXX program that processes many files and it seems to do the first few of them and then just quits, chances are you are forgetting to close files.

The choice between using the CHAR functions or the LINE functions boils down to exactly what you want to accomplish. The LINE functions are very convenient for processing text files like e-mail messages and news postings, but you will find it slow if the files are large. A more efficient way of reading large files is to read them in large chunks with CHARIN. Compare the times it takes for the above program to read the data file with this one:

/* Count lines in a file */
Parse Arg File
crlf=d2c(13)||d2c(10)
Time1=Time("E")
Time1=Time("R")
Data=CHARIN(file,1,CHARS(file))
Time2=Time("E")
ET=Time2-Time1
Say "It took" ET "seconds to read the file."
rc=Stream(file,"C","Close")
i=1
Do While Data<>""
   Parse Var Data Data.i (crlf) Data
   i=i+1
End
Say "There were" i-1 "lines in" file
Exit
You will find that the latter program reads the data file much faster because it reads the file in bigger chunks, which allows OS/2 to buffer the input more efficiently. Depending on how many parsing instructions have to be executed, it may be faster to use this method. Note that we explicitly added the carriage return and linefeed pair after reading the data because we used them as the parsing token. You'll also see that we used a variable Data and a stem variable Data. without any complaints from REXX. To REXX, they are two different variables.

The REXX input/output functions are flexible, and for the most part, intuitive. You can even use them to perform input/output operations on devices like the COM ports. A couple of years ago, I wrote a REXX program that controlled a modem using the CHAR functions. With a small amount of code, you could write a program to transfer files between two computers with a null modem connection between their serial ports or control your printer through the parallel port. Once again REXX shows its ease of use wrapped around powerful capabilities.


Dr. Dirk Terrell is an astronomer at the University of Florida specializing in interacting binary stars. His hobbies include cave diving, martial arts, painting and writing OS/2 software such as HTML Wizard.

[Index]  [® Previous] - [Feedback] - [Next ¯]

[Our Sponsor: F/X Communications - Home of the InJoy dialer, #1 in OS/2 shareware (Jan-97).]


This page is maintained by Falcon Networking. We welcome your suggestions.

Copyright © 1997 - Falcon Networking