We discuss now how one can access data in files directly or randomly instead of sequentially.
We have already told you that CMS can find each individual record of a file directly, thanks to is index structure.
How to request specific records directly depends on the File I/O method. Let's first suppose that we want to read one single record. The different I/O methods give then:
/* Reading one specific record */ address command parse value '75 MY FILE A' with lnum fileid /******* EXECIO *******/ 'EXECIO 1 DISKR' fileid lnum '( VAR RECORD' /******* XEDIT ********/ queue ':' lnum queue 'COMMAND STACK 1' queue 'COMMAND QUIT' 'XEDIT' fileid '(NOPROF' /******* LINEIN *******/ record=linein(fileid,lnum,1)
Note: The file is not closed in the examples above, except with the XEDIT solution.
If we now look at how we can read 10 consecutive records starting from absolute record 75, then we have:
/* Reading one specific record */ address command parse value '75 10 MY FILE A' with lnum nrec fileid /******* EXECIO *******/ 'EXECIO' nrec 'DISKR' fileid lnum '(STEM RECORD.' /******* XEDIT ********/ queue ':' lnum queue 'COMMAND STACK 10' queue 'COMMAND QUIT' 'XEDIT' fileid '(NOPROF' /******* LINEIN *******/ call stream fileid,'COMMAND','LINEPOS ='lnum 'READ' /* set read ptr */ do i=1 to nrec record.i=linein(fileid) end
Another example where XEDIT can be handy is when you want to include part of one file into another:
queue '/USER ABC/' queue 'COMMAND GET USER INCLUDES A 25 10' queue 'COMMAND FILE' 'XEDIT SOME FILE A'
In this example, you edit the file SOME FILE A, position at the first record containing USER ABC and imbed records 25 to 34 (10 records) from file USER INCLUDES A.
Until now, we didn't include examples for CMS Pipelines here. We will have examples later.
We will not extend on the matter here, but note that it is also possible to directly access file records on Personel Systems. The files need however to have a fixed record length structure, that is, each record must have the same number of characters. Then, using the SEEK command of the STREAM() function, it is possible to extract a specific record directly.
You will often need to process records of a file based on specific strings they contain. It is of course possible to select the proper records with pure REXX coding (this is even the only way when you read the files using Stream I/O or CSL methods).
But, EXECIO, XEDIT and CMS Pipelines have again an added value in this case. These commands have the possibility to extract records based on the presence of a string. This results in some storage savings, and as the logic used by these commands is not interpreted but compiled, the process may be much faster than with REXX.
So, REXX has the greatest flexibility (you can select records with more precision, use arithmetic comparisions, etc.). Next comes CMS Pipelines which has also plenty of selection filters. XEDIT and EXECIO close the line with the least possibilities.
You should always keep in mind that I/O processing is the time consuming part of your programs. So, for example, if you have to combine multiple selections, it will be beneficial for performance to keep the file in storage. XEDIT and REXX(footnote) are the easiest in this case. CMS Pipelines is less obvious for novice plumbers, while EXECIO does not allow you to process records from storage.
XEDIT, EXECIO and CMS Pipelines have both the LOCATE and FIND (sub)commands. From experience, we know that the differences are not well understood, so let's expand a little bit :
LOCATE :
This subcommand will search for a given, delimited character string in that part of the records that is called the zone. The string can be located anywhere inside the boundaries of the zone, which by default spans the complete record.
The different tools let you LOCATE(3) a string in a zone as follows :
Notes :
FIND :
This subcommand looks for a given string that starts at the beginning of the record or at a given column. As you can understand, this search needs less machine processing, so that you should prefer this function to LOCATE whenever possible.
The different command formats are :
Notes :
'FIND USER MAINT '
will match both MAINT and MAINTSNA, while a
'LOCATE /USER MAINT /'
will only match MAINT !
You have to specify
an underscore (_) if you want to search for a blank. So, in order to
find MAINT only, you would use the command
'FIND USER MAINT_'
PIPE only searches from the beginning of the record, but it is of course possible to temporarily re-arrange the record layout prior to issuing the FIND stage, or, by using ZONE.
For EXECIO, the only difference with LOCATE is that FIND limits the search to the start of the zone.
EXECIO nlines DISKR fileid (LOCATE /string/ or EXECIO nlines DISKR fileid (FIND /string/
then nlines does not specify how many records should be returned, but only how far EXECIO has to scan for the string.
For example, if the first record containing the string MAINT is the tenth record in the file, then a
EXECIO * DISKR USER DIRECT A 4 (FIND /USER MAINT /
will return following records:
6 10 USER MAINT PASSW ...
The relative record position is 6 as we started to search from record 4, while the absolute record position is of course 10.
relrec=4 do i=1 by 1 'EXECIO * DISKR USER DIRECT A' relrec '(LOCATE /USER /' if rc<>0 then leave /* end of file */ parse pull relrec absrec . parse pull rec.i relrec=0 end rec.0=i-1
This is the end of the chapter. Chapter 17 will discuss output operations.
In this case, some I/O method brought the records into storage and
assigned them to a REXX stem.
Back to text