RexxFile: File I/O routines ( vs 4.00, January 2003)

The class RexxFile contains a complete object oriented implementation of the character/line oriented I/O routines of classic REXX, namely stream, linein, lineout, lines, chars, charin and charout, as well as a couple of utility routines useful for File I/O in general. The old function oriented calling sequence is provided for convenience as well.

The Rexxfile package may be used in any NetRexx/Java program as well. In this case, you should add the statements

Import Rexx2Nrx.Rexx2RT.RexxFile

Class class-name[parameters] USES RexxFile

to your program.

Note, that the Rexx2Nrx translator replaces the original, function oriented calls by object oriented method invokations whenever possible, and also substitutes constant parameters given by the proper properties of the RexxFile object.

Note, that in particular, variations of the various stream-commands are directly replaced to use the proper properties/methods of the RexxFile object whenever possible,

 

Public Properties of a RexxFile object:

For each RexxFile-Object, the following public properties are maintained:

FileNo = Int 0  unique RexxFile File-Number
FileFile = File Null the associated FILE object
FileName = Rexx '' the actual given file name, blank is console
FileFullName = Rexx ''  the full name of the file (including path)
FileAccess = Rexx ''  the file access method requested (see below)
FileStatus = byte 0   the coded File Status 
  •  -2: file already closed  
  • -1 = EOF already encountered (but file still opened), 
  •     0 = not yet opened (= not yet accessed);
  •     1 = ready for input
  •     2 = ready for output(rewrite)
  •     3 = ready for append(write at end of file)
  •     4 = ready for update
  •      5= Lines in Core (buffered line-oriented I/O)
FileOrganisation = byte 0  The files Organisation
  • -1 = Unknown
  • 0 = not available
  • 1 = Sequential
  • 2 = Random

 

FileRecType = char  the record type indicator
  • 'V' = variable length records
  • ,F‘ = Fixed length records
  • ,N‘ = No record structure at all
FileRecLen = int 0 the Files record length (if available)
  •    0 = variable length records
  •  >0  = record-length in bytes when given
FileDTS = Rexx '

The Files Date Time Stamp (at open time) in the ISO format YYYY-MM-DD hh:mm:ss nnnn 

existing = boolean 0 the original value of exists() at open time.
  • 0 = new file, did not exist at open time
  • 1 = file did already exist (before open)

 

CurLine = Rexx '' the current (last) line read/written from this File
CurLineNo = int 0 the current (last) line-number read/written
pendingLine = boolean 0 flag for pending line (for lines())
needsUTF = boolean 0  the UTF read/write flag
  • 0 = no UTF encoding required/wanted
  • 1 = read/write with UTF encoding

 

FileSize = long -1   old file-size in bytes, when available
  • -1 = not yet known
  • -2 = not available on this operating system
FileNumberOfLines = Int -1   total Number of Lines of this File, when available
  • -1 = currently unknown number of lines
FileLinesBuffered = boolean 0

(when opened with ‚READ LINES‘ or ,UPDATE LINES‘)

Flag indicating if lines of File are buffered in core
  • 0 = File lines are read/written when requested 
  • 1= all lines of the file are held in core

 

FileLines = Rexx '' 

Indexed String(=Stem) of all Lines in core, with the line-number as the index.

  (only filled when FileLinesBuffered is 1)

FileLinePosRead  the Files Line Read position (core-buffered random line I/O)
FileLinePosWrite  the Files Line Write position (core-buffered random line I/O only)
FileReadLocation = long 1 Read Location in bytes (record oriented random files only, first byte is 1)
FileWriteLocation = long 1 Write Location in bytes (record oriented random files only, first byte is 1)

 

 

Private RexxFile Properties:

Internally, the various access methods are managed thru attached Java Input/Output streams, but the relevant RexxFile properties are currently deliberately hidden from the user, and included here for documentation purposes only.

 

AttachedFIS = FileInputStream null
attached Java File-Input-stream
AttachedBIS= BufferedInputStream null 
att. Java buffered input stream
AttachedDIS = DataInputStream null 
attached Java Data Input Stream
AttachedFOS = FileOutputStream null 
attached Java File-Output-Stream
AttachedBOS = BufferedOutputStream null
attached Java  buffered output
AttachedDOS = DataOutputStream null
attached Java Data Output Stream
AttachedRAF = RandomAccessFile Null
attached Java RANDOM-File
 
 

 

note that RANDOM access is only used for charin(text,start) and charout(text,start)! all other variants are resolved with buffered I/O streams (more than 10  times quicker!)

 

Public methods:

RexxFile has a single constructor method, RexxFile(filename), which will create a new object on every call.

method RexxFile(name=Rexx)

returns a unique RexxFile-Descriptor (FD) for a given File-name. Note, however, that each call (even with the same file name) creates a new RexxFile object. Use the RexxFile.FD(name) method (described below) to get a unique RexxFile-Object by File-Name.

method FD(name=Rexx) public static returns RexxFile

a function returning the RexxFile File descriptor (FD) of a given filename.if the object(filename) is already known, this corresponding FD is used. If not, a new RexxFile object is created.

method access(access_method=Rexx) returns RexxFile

                 where access_method may be one of the following

INPUT, READ
read access (sequential)
OUTPUT, REWRITE, REPLACE
write access (sequential, overwriting the existing content of the file!)
EXTEND, WRITE, APPEND 
extend access (sequential, adding records to the file)
UPDATE  
Update acesss (sequential/random)

 

when needed, the actual access method may be suffixed by one or more of the following modifiers:

RANDOM for RANDOM access (record oriented)

LINES for RANDOM access (line oriented). Note, that in the latter case all lines of the file are read into core when the ‚READ LINES‘ access-method is used, and written back to the file at file close time only!

UTF UTF8 encoding requested.

Examples:

FD_input = RexxFile.FD(;myfile.txt‘).access(‚READ‘)

Builds a unique File-descriptor for file ‚myfile.txt‘, and checks if the file exists. If ist does not exist, an appropriate error message is displayed and the program is aborted. Use the exists() method if you want to check the file first by your own.

FD_input=RexxFile.FD(‚myfile.txt‘).access(‚READ LINES‘)

Reads all lines of ‚myfile.txt‘ into core. Note that the access function does return the RexxFile object, whereas open returns a result String.

 

Public File Access methods:

method open(access_method) public deprecated

ancient form for access. Note that open returns ‚READY:‘, as specified for the stream function, whilst access returns a RexxFile object

method exists() returns boolean

returns boolean 1 if this.File exists, 0 if it does not exist.

method scratch() final

scratches this.File (deletes the files content, when present, otherwise creates a new empty file)

method extend() final

creates this.Filename, if file does not yet exist, and opens it for write. Appends to the file, if file does already exist

method close() final

flushes any pending buffers and closes this.file, if open. No action, if file is not open (not accessed)

method erase() public deprecated

erases (deletes) a given file. Historic, use RexxFile(fid).delete() instead.

method stream(stream_name=Rexx '', operation=Rexx '', command=Rexx '')-

public static deprecated returns Rexx

normally, all stream commands, when given literally, are translated to the proper methods by the classic Rexx to NetRexx converter. The stream function is available for applications which need to build the command strings on the fly, and are translated to the proper methods above at run time..

 

Inherited methods of any RexxFile object

The class RexxFile extends the Java class File, and therefore the follwowing properties and methods are inherited from the Java File class:

exists()  a boolean returning 0 is the file does not exist, and 1 if it does exist
length()  the actual persistent file length (in bytes!).
CanRead()  true (=1), if the given file can be read
CanWrite()  true(=1) ,i f the given file can we written

IsHidden() 

true(=1) , if the file is hidden, i.e will not be shown by the DIR command

IsFile()

true(=1) , if the given FileName designates a File.
IsDirectory()   true(=1) , if the given FileName designates a Directory.
IsAbsolute()   true(=1), if the given FileName did conatin an absule path specification
LastModified()   the last modification, expressed in milliseconds past 1.1.1970. But note that also the property FileDTS and the function DTS() are available,which will give you the accurate Date Time Stamp in a more meaningful notation.
   

see the Java documentation for a more elaborate description of these properties and methods.

 

Date & Time of Last modification, FileFormat, and FileInfo:

method DTS(file=Rexx) static public returns Rexx

returns Date Time Stamp of an existing file in the format YYYY-MM-DD hh:mm:ss nnnn. Returns the null string when the file does not exist..

method FileDateTime() public deprecated returns Rexx – old American format

Historic: Date & Time of last file Modification in the american Format: returns MM/DD/YYYY hhmmss when the file exists. returns null string, when the file does not exist.  

Historic, use FileDTS unstead !

method FileTimeStamp() public deprecated returns Rexx –old EUROPEAN format

Historic: Date and Time of the last file Modification in the EUROPEAN Format:.Returns YYYY-MM-DD hh:mm:ss when the file exists. Returns null string, when the file does not exist.



The routines FileDateTime and FileTimeStamp are used for upward compatibility to other Rexx Implementations only, and should be replaced by the DTS function (or the property FileDTS).

Line oriented I/O methods (working with the current RexxFile object)

method lines() final returns int

returns 0, if end of file is reached.

returns remaining number of lines, if this information is available.

returns 1, if number of lines is not available on this operating system, and EOF is not yet reached. .

method linein() public final returns Rexx

get next line from this.File

method linein(line_no=int) public final returns Rexx

Get line with given line number. Implies access-method ‚READ LINES‘. Note that when the file is accessed with  ‚READ LINES‘ or ‚UPDATE LINES‘, the lines are already held in core and this operation is very quickl

method linein(line_no=int ,count=int 1) public final returns Rexx    

Both versions imply access-method 'READ LINES'.

method lineout(oline=Rexx) public final returns int

sequential line-oriented IO: put output oline to current Output-Line-Number.

method lineout(oline=Rexx,oline_no=int) public final returns int

random line-oriented I/O: put output line to given line number; implies access(‚UPDATE LINES‘) when no access method has been specified). Also note, that when UTF-encoding is required, changed lines might also change their length. With the core buffering techniques available you will not

loose any existing information, as the new file (with UTF encoding) is written at once when the file is closed!

method lineout() public deprecated

historic; note that empty lineout is CLOSE in classic REXX!!

 

Character oriented I/O methods:

method chars() public final returns long

return number of remaining characters in the given RexxFile, when available. Returns 0, when EOF is encountered.Returns 1, if the number of remaining characters is not available, but EOF has been still not reached. If the designated file is the console, a null string terminates console input.

method charin() public returns Rexx

reads a bunch (chunk) of characters, starting at the current file location. Returns a null string at EOF.

Attention: this function does currently NOT read a single character, as specified in .classic Rexx‘, but a chunk of 8 Kilobytes at once to improve performance. Is this a wise decision ? Comments are welcome.

method charin(n=int) public returns Rexx

read n bytes from current File Read location.

method SeekTo(start=long) public returns long

seeks to a given starting byte location. Only available for RANDOM record oriented files.

The first byte of the file is byte 1 (not 0 like in Java). The next available FileReadLocation is returned, i.e. the next charin/recin call will start at the given location.

 

method charin(start=long) public returns Rexx

reads a bunch (chunk) of characters, starting at the given File-Location. The File-location is measured in bytes. First byte of File is 1 (not 0, as in Java).

method charin(start=long,n=int) public returns Rexx

reads n bytes, starting at location start, and returns it as a Rexx String..

method charout(text=Rexx) final returns int

puts out text at the current file location.     

method charout(text=Rexx,start=long) final returns int

                        puts out text at the file-location start (in bytes, first byte is byte 1).

method charout() public deprecated

historic; empty charout is equivalent to ‚close‘ in classic REXX!

method load_lines() public 

loads entire line-numbered file to core. Called internally, when access-method 'INPUT LINES', 'READ LINES', or 'UPDATE LINES' is used.

method save_lines() public

save entire line numbered file from core. Called implicitely for files opened with 'UPDATE LINES'.

 method closeAllFiles() public static

Closes all opened RexxFile objects. This routine will be automaticely invoked ‚on exit‘ to ensure that all pending buffers are written back to disk. Also note, that the LOG-file, if present, is always closed as the last file!.

method erase(f=Rexx) public static deprecated

erases (deletes) a given file. Historic, use RexxFile(fid).delete() instead.

method purge(flist=Rexx) public static deprecated

Purges (erases) a list of given files. The entries are separated by a semicolon, for instance.

Historic name (of GE’s MARK III service): example:

purge(‚abc.def;myfile.xxx;c:\mydir\catalog.file‘)

no action, if the file(s) do(es) not exist.

 

File Description Routines:

As the original classic Rexx implementation did not specify file I/O, a couple of very similar routines have been implemented with very similar, but not indentical purposes in the various Rexx implementations.

Currently, the RexxFile package attempts to provide the union of the possible calling sequences. The overhead is very small, as each of them only need a few lines of coding.

method length(f=Rexx) static public returns long

returns length of file in bytes. Returns 0 when file does not exist.

method fullname(f=Rexx) static public returns Rexx

returns the full file name (real name) of a given file. This method is equivalent to the Java method  File(file).getAbsolutePath().

If the File is null, the Full Filename is a Null string, the console is designated..

method FileFormat() public deprecated returns Rexx -- CMS QUERY format

returns FileRecType' 'FileRecLen

method FileInfo() public deprecated returns Rexx -- CMS QUERY Info

returns FileFormat() FileNumberOfLines FileDateTime()

method fileid(fn=Rexx '', ft=Rexx '',fp=Rexx '') public static returns Rexx

builds a file-id according to opsys conventions.A file-id is a unique string identifying a single file: It may either already exist, or might be created with scratch.

method parsefid(f=Rexx) public static returns Rexx

parses a given file-id (according to the operating system conventions) and returns the result in the format

fn ft fp (filename, filetype, filepath, separated by a space)

Historic, needed for CMS compatibility only.

method filename(f=Rexx) public static returns Rexx

returns the filename part of a given file-id (without the path and the file-type!!)

method filetype(f=Rexx) public static returns Rexx

returns the filetype part of a given file-id

method filepath(f=Rexx) public static returns Rexx

returns the file-path (including the drive letter!)

method ispacked(f=Rexx) public static returns boolean

tests if a file is packed (on CMS). Currently returns always 0 in Java.

method isopen(f=Rexx) public static returns boolean

returns boolean 1 if the given file has already been opened (or accessed) successfully.

 

method filespec(option=Rexx, f=Rexx) public static deprecated returns Rexx

the filespec function is provided for OS/2 compatibility.

Option may be one of the following:

otherwise aborts with the error-message: 'unknown option in filespec('option','spec')')

method nametype(f=Rexx) public static returns Rexx

returns the FileName including the file-type

method filedrive(f=Rexx) public static returns Rexx

returns the file-drive part of the path

method sysfileid(f=Rexx,ft=Rexx) public static returns Rexx

searches for a system file. First., it attempts to read the given file in the current directory. If the file exists, this is used. When the file does not exist in the current directory, it is searched in the directories specified in the classpath-variable. When the file exists, the routine returns the full file name (including path).

method traceio(itrace=int 1) public static

This is a debug aid setting the desired level of tracio. The available codes for itrace are:

0 = no trace

1 = trace open/close/delete

2 = trace input lines

3 = trace output lines

4 = debug IO (trace all utility routines)

-1 = trace Current file changes

the function tracio may be used to debug a given program by looking at the IO it performs.

Deprecated functions/subroutines:

 

Deprecated STATIC methods (old classic Rexx style calling sequence with given Filename)

method exists(f=Rexx) public static deprecated returns boolean

returns boolean 1 if given file exists, 0 if it does not exist

method open(f=Rexx, access_method=Rexx '') public static deprecated

ancient form for access. Note that open returns ‚READY:‘, as specified for the stream function,

whilst access returns a RexxFile object

method read(f=Rexx) public static deprecated -- open for read

historic; does NOT read any line, but opens for read

method scratch(f=Rexx) public static deprecated

scratches given filename (deletes the files content, when present, otherwise creates a new empty file).

 

method append(f=Rexx) public static deprecated

creates given.filename, if file does not yet exist. Appends to the file, if file does already exist.

method close(f=Rexx) public static deprecated

flushes any pending buffers and closes given fileName, if open. No action, if file is not open (not accessed)

 

Deprecated Line oriented I/O functions (old classic Rexx style calling sequence)

method lines(f) public static deprecated returns int

returns 0, if end of file is reached. Returns remaining number of lines, if this information is available.

returns 1, if number of lines is not available on this operating system, and EOF is not yet reached.

 

method linein(f) public static deprecated returns Rexx

historic; get next line from given filename f.

method linein(f,line_no=int,count=int 1) public static deprecated returns Rexx

historic; count must be 0 or 1. When count is 1, then get line with given line-number: If count is 0, position file to given line number.

method lineout(f=Rexx,oline=Rexx) public static deprecated returns int

sequential line-oriented IO: put output oline to current Output-Line-Number of given FileName f .

Deprecated character oriented I/O functions (old classic Rexx style calling sequence)

method chars(f=Rexx) static public deprecated returns long

        returns the number of remaining characters of the file.

method charin(f=Rexx) public returns Rexx

returns a bunch (chunk of size 8k) of characters, if available. Otherwise as max. characters (<8k) which are available.

method charin(f=Rexx,start=long) public deprecated returns Rexx

        returns a bunch of characters, starting at location start. 

method charin(f=Rexx,start=long,n=int) public deprecated returns Rexx

returns a string of n characters, starting at location start.

method charout(f=Rexx,text=Rexx) public static deprecated returns int

put characters out at current write position. No end-of-line-characters added!

method charout(f=Rexx,text=Rexx,start=long) public static deprecated returns int

set write position to start (byte locaton, first character of file is 1!), and put characters out as above.

Utility routines and minor methods:

method unpack(packed_fid, fid) public static

this method is currently un-used in Java, and only used for CMS compatibility.

Maybe we could use this method for zipped or jar‘ed files ?!?

 

Public static properties:

The following static properties are initialized at the first invokation of class RexxFile:

$props=System.getProperties() he system properties
$classpath=$props.getProperty('java.class.path') the current Java classpath
$path=$props.getProperty('java.library.path') the current library path
$fs=$props.getProperty('file.separator')              file separator (in a file-list)
$ts='.' /* type separator */  type separator (currently always ‘.‘)
$ps=$props.getProperty('path.separator')  path separator
$ls=$props.getProperty('line.separator')  line separator
$ls_length=$ls.length()  length of line separator
$InLine = Rexx ''  most recent input line
$InFile = Rexx '' 

FileName of most recent input file read, blank for console

$InLineno = int 0  most recent input line number, if available
$InPointer = int 0  current parse pointer, if available
   
   
   
   
   
Ready=Rexx 'READY:'  Ready msg for stream command
   
   

 

 

Examples: