READS
Read the next sequential record
WSupported on Windows
|
USupported on Unix
|
VSupported on OpenVMS
|
NSupported in Synergy .NET
|
READS(channel, data_area[, label][, REVERSE][, DIRECTION:dir_spec] & [, GETRFA:new_rfa][, LOCK:lock_spec][, NOFILL][, WAIT:wait_spec]) & [[error_list]]
Arguments
channel
The channel on which the file to be read is open in input, output, append, or update mode. (n)
data_area
The variable that receives the information. (a)
label
(optional) A label to which control is passed if an “End of file” error ($ERR_EOF) occurs.
REVERSE
(optional) Only valid with Synergy ISAM and relative files and specifies that the record is to be read sequentially in the reverse direction. This qualifier is deprecated; we recommend you use DIRECTION instead.
DIRECTION
(optional) Only valid with Synergy ISAM and relative files and specifies a forward or reverse sequential read. See DIRECTION for a complete description.
GETRFA
(optional) Returns the record’s RFA after the READS has been performed. See GETRFA for a complete description.
LOCK
(optional) Only valid with Synergy ISAM files and specifies whether the record is to be locked after the READS has been performed. See LOCK for a complete description.
NOFILL
(optional) Prevents the data area from being padded with blanks when the data returned does not completely fill data_area. See NOFILL for a complete description.
WAIT
(optional) Specifies how long to wait for a record lock to be released. See WAIT for a complete description.
error_list
(optional) An I/O error list. If any one of the specified errors occurs as part of the READS, control is transferred to the associated label.
Discussion
This Discussion includes the following subtopics:
The READS statement retrieves the next available record according to the collating sequence of the index of reference (i.e., whether the key is ordered ascending or descending). If DIRECTION:Q_REVERSE (or the deprecated REVERSE) is not specified, READS retrieves the record that logically follows the record that was most recently read from or written to the file. The next record context is established as follows:
For file type |
The context is established as |
---|---|
ISAM |
The first record in the file for the primary key when the file is opened. If a READ is performed, the next record follows or precedes the record read (depending on the DIRECTION qualifier) in the order of the specified index. If a FIND is performed, the record read by a READS is the last record positioned to by the FIND. The next record is not affected by a STORE, WRITE, or DELET. |
Relative |
The first record in the file when the file is opened unless the POSITION qualifier is specified on the OPEN statement. If a READ is performed, the next record follows or precedes the record read (depending on the DIRECTION qualifier). If a FIND is performed, the record read by a READS is the last record positioned to by the FIND. The next record is not affected by a WRITE. A WRITES updates the context so the next record follows the record written by the WRITES. |
Stream and sequential |
The first record in the file when the file is opened unless the POSITION qualifier is specified on the OPEN statement. If a READ is performed, the next record follows or precedes the record read (depending on the DIRECTION qualifier). If a FIND is performed, the record read by a READS is the last record positioned to by the FIND. WRITE and WRITES update the context so the next record follows the record written by the WRITES, WRITE, or PUT. |
By default, READS locks the record, unlocking any previous automatic lock. If channel is open in update mode and READS tries to access a locked record, a “Record is locked” error ($ERR_LOCKED) is generated. If the program does not trap the error, it is considered fatal.
If the file record size is less than that of the data area, the record is placed into the data area left-justified over blanks. If the file record size is greater than the size of the data area, only the leftmost portion of the record is transferred, and an “Input data size exceeds destination size” error ($ERR_TOOBIG) is generated. (If system option #27 is set, this error is not generated; this option allows a larger buffer to be stored into a smaller destination.)
With the ability to read reverse, beginning of file (BOF) and end of file (EOF) are both treated as the file “end.” When we refer to EOF, we mean either end of file or beginning of file.
A READS on an empty file positions you to the end of the file, not the beginning. Therefore, if you perform a READS on an empty file followed by a STORE, the next READS statement generates an “End of file” error ($ERR_EOF).
If you attempt to read the record following the last record in a file, you’ll get an “End of file” error ($ERR_EOF). When this error condition occurs, the current record position becomes undefined.
If REVERSE is specified but label is not, a comma is still required as an argument placeholder. Specifying DIRECTION:Q_REVERSE (or the deprecated REVERSE) enables you to re-enter a file sequentially after reaching the end of file. You may not receive the record that was previously read, however, because the end of file moves as records are added to the file. A sequential READS back into the file reads the first or last record that is currently in the file.
The first READS that follows a FIND on the same channel ignores the DIRECTION (and the deprecated REVERSE) qualifier and retrieves the record that was positioned to by the FIND.
See the warning in Error trapping for information about inconsistencies that may occur after an I/O error is encountered. |
A READS from the terminal behaves differently on Windows than on other platforms. On Unix and OpenVMS, any text that was previously displayed at the location of the READS remains displayed until the user types over it. On Windows, this text is erased for the width of the buffer passed to READS. The reason for this difference is that on Windows, the input is performed using an edit control to give the user the benefit of editing features (arrow keys, Home/End, cut/copy/paste, and so forth). For text to be displayed within the edit control, it must also be returned to the program if the user merely presses Enter. This is not operationally equivalent to the behavior on Unix and OpenVMS, where the text, although displayed, is not returned in the READS buffer unless the user types it in. We therefore opted for keystroke compatibility, as opposed to visual compatibility, with other systems. The behavior on Unix and OpenVMS is actually the less consistent of the two, but because it has historical precedent, we cannot change it without breaking existing code.
Also on Windows, the F10 key is a reserved key that activates the system menu. It will not be returned to your application when using READS, but it will be returned in a UI Toolkit application.
If you have a telnet terminal connection, see $ERR_IOFAIL for more information.
If you want to prefill an area for input on Windows, use a different input method. Alternatives include various UI Toolkit routines (I_INPUT, I_INPFLD, U_FLD) or the Synergy windowing API routine W_FLDS with the WF_INPUT subfunction.
Don’t use READS with the low-level Synergy windowing API routines, because it displays characters in a “console” window. In addition, READS should not be used for interactive programs on Windows; it should only be used for command line-type programs (for example, those used with dbs.exe). If you’re migrating software to Windows, we recommend that you upgrade your programs to use the low-level windowing routines for screen display and input instead. |
For Windows non-interactive and .NET runtimes, READS does not honor the WAIT qualifier and will wait forever for a terminating condition. (However, WAIT does work when running a .NET application on Linux.) In addition, READS from a channel opened to TT: does not honor activation characters (nor does it honor the MASK qualifier, even though the compiler won’t generate an error if it’s specified).
For the regular runtime (dbr) on Windows, certain Windows reserved characters, such as tab, cannot be input with READS from TT:.
READS retrieves records in the order of the key of reference accessed by the last FIND or READ on the channel. If READS is the first I/O action on the channel, the input is processed by the first data record of the primary key index. You can also use READS to retrieve ISAM records with duplicate keys after a READ has located and retrieved the first record of the set.
On Windows and Unix, characters are read from the file to the data area until one of the following conditions occurs:
- A record terminator is encountered.
- The data area is filled.
- The end of file is encountered.
If the data area is filled before a record terminator is encountered, an “Input data size exceeds destination size” error ($ERR_TOOBIG) is generated, and input characters are ignored until one of the other conditions occurs. If a record terminator is encountered before the data area is filled, the remaining space is filled with blanks. (Valid record terminators in Synergy are ASCII values 10 through 12, and 13 when followed by 10 on Windows.)
On OpenVMS, for nonstream files, the next record is read into the data area.
For terminals or serial devices, READS behaves as stated for Windows and Unix above, with the following additional rules:
- If the FLAGS subroutine’s position 9 is set, which terminates a field entry implicitly when the field is full, no error is generated when the data area is filled.
- Additional terminators can be defined using the ACCHR subroutine. The terminator can be found using %RTERM (or %RDTRM). The number of characters read can be found using %SIZE.
- The terminator for READS is returned in %RTERM (and %RDTRM) and is not part of the returned characters in the data area, nor is it part of the read length.
If you read the last record in a file and want to retrieve that record later, unless the file is open in exclusive mode, you can’t guarantee that the same record is at the end of file. Use %RECNUM to get the record number or to capture the RFA of the current end of file, then retrieve that record specifically later. |
Prefetching records to improve performance with xfServer
To improve sequential READS performance when using xfServer, a prefetch feature is available that enables the client to prefetch (or buffer) sequential records for files of any type that are open in input mode, relative files that are open for update, or ISAM files that are open for update and use the LOCK:Q_NO_TLOCK option.
Prefetching is off by default. To turn prefetching on, set the SCSPREFETCH environment variable to a value between 1 and 32, which specifies the size of the prefetch buffer in kilobytes. To turn prefetching off, set SCSPREFETCH to 0. You can enable or disable prefetching on a file-by-file basis by using the SETLOG routine to set or clear SCSPREFETCH prior to the OPEN statement. The value of SCSPREFETCH is checked on every remote file open.
Prefetching is not allowed in the following instances:
- When a READS with DIRECTION:Q_REVERSE (or the deprecated REVERSE) is performed on an ISAM file on a key with duplicates.
- When a READS with a lock follows a READS(LOCK:Q_NO_TLOCK) on a channel open for update on an ISAM file on a key with duplicates.
If you use prefetching in either of these cases, a “Sequential read caching error” ($ERR_SEQRDS) will occur. If this happens, immediately try doing a keyed READ to reset your current position.
To use prefetching without modifying your code, you can set system option #55, which automatically maps READS with LOCK:Q_NO_LOCK to READS with LOCK:Q_NO_TLOCK.
See also
Input and output statement qualifiers
Examples
The following example scans through an entire relative file looking for a specific record.
subroutine find_rec a_chn ,d ;Relative file channel .include "REC:who.rec" ;Record "who" includes field "name" record srch_name ,a20 proc xcall flags(4020, 1) display(TTCHN, "Name to find: ") reads(TTCHN, srch_name, done) find(a_chn, who, ^first) repeat begin reads(a_chn, who, none) if (name .eq. srch_name) exitloop end writes(TTCHN, who) done, sleep 1 display(TTCHN, $scr_clr(screen)) xreturn none, writes(TTCHN, "No record found") goto done endsubroutine