问题
I've been seeing a lot of examples for reading a sequential file in COBOL that looks something like this:
FD File-Record
01 Input-Record.
88 End-Of-File VALUE HIGH-VALUES.
05 ...
...
READ File-Record
AT END SET End-Of-File TO TRUE
END-READ
PERFORM UNTIL End-Of-File
PERFORM Process-Record
READ File-Record
AT END SET End-Of-File TO TRUE
END-READ
END-PERFORM
One question is, would it be just as well to process it as follows?
PERFORM UNTIL End-Of-File
READ File-Record
AT END SET End-Of-File TO TRUE
NOT AT END PERFORM Process-Record
END-READ
END-PERFORM
I've not generally seen the second pattern, but it seems more concise and less redundant to me. Is there a problem with it versus the first? I'm not referring to variations on the theme above (they can be grouped differently depending upon how you define what you PERFORM
on) but I'm referring to the concept of the first record pre-read pattern, which seems to be favored in various examples I've seen.
回答1:
The first is called a "Priming Read". Using this means there is always a record available going into the processing loop.
The second is called... well, not sure that's got a name. Within the processing loop the availability of a record has to be tested for.
A couple of things. Using the AT END/NOT AT END/END-READ
is in itself somewhat unwieldy (opinion). There is a cleaner way (two reasons for it being cleaner).
On the SELECT statement for your file (you should do this for all files) define a FILE STATUS
field, individual per file.
After every file-access, test the file-status field for that file, and ensure the access gave an expected result.
Using this method, the file-status field will be automatically set to 10
when end-of-file is reached. So you move the 88 to the file-status field, and change the VALUE
to 10.
01 INPUT-FILE-STATUS PIC XX.
88 INPUT-FILE-OK VALUE ZERO "10".
88 INPUT-FILE-EOF VALUE "10".
PERFORM PRIMING-READ
PERFORM UNTIL End-Of-File
PERFORM Process-Record
PERFORM READ-A-RECORD05 is optional file not present, 23 is record not found.
END-PERFORM
...
PRIMING-READ.
PERFORM READ-A-RECORD
IF INPUT-FILE-EOF
[cancel with end-of-file on first read message]
END-IF
.
READ-A-RECORD.
READ File-Record
IF NOT INPUT-FILE-OK
[code here to check file-status field and crash if bad]
END-IF
.
I strongly favour the priming-read. An "empty" file may indicate a problem. Now you can test (after the priming read) without having to clutter your main logic. You don't have to "get out of the loop" at end-of-file, because the loop is only ever entered with a current record.
Traditionally files would contain "headers" (and "trailers"). The header would contain a date, logical-file-name, etc. The header would be read and verified to know that the correct file was being processed. Then you need to check that there are not two headers (because if you don't, one day there will be). Whilst you've done that, you already have the first data record.
You don't want to do all that in amongst some "business" logic or to clutter the flow of the logic.
On the 88 on the input-record, be aware that this is non-transportable across other COBOLs. On an IBM Mainframe, for instance, unless your input is variable-length records and you use APPLY WRITE ONLY (explicitly, or implicitly by the horrible compiler option AWO) then accessing data under an FD before a file is open, after it is closed, or after end-of-file will lead to a crash (ABEND).
回答2:
The main issue is that you only call PERFORM Process-Record
once, so in this respect there is no improvement in the second pattern.
Then you are working in Cobol but are worrying about the finesses of patterns. I would rather worry about working in Cobol versus higher/newer languages. Some 25 years ago I used Protos
as a layer to hide raw Cobol . . .
来源:https://stackoverflow.com/questions/28700006/pattern-for-reading-a-sequential-input-file