MODULE 8 · SEQUENTIAL FILES · 2/8

Reading a file with the priming read

14 min30 XPExercise

Reading a sequential file means: open it, read records one at a time until there are none left, close it. The only tricky part is knowing there are none left.

AT END

READ file-name fetches the next record into the FD's record area. When there is no next record, the READ fails with an end-of-file condition, and the AT END phrase runs instead. The record area is then undefined: never process it after AT END.

The standard way to use this is an end-of-file flag with an 88-level condition name, and a priming read:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. READDEMO.
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT CUST-FILE ASSIGN TO CUSTIN
               ORGANIZATION IS LINE SEQUENTIAL.
       DATA DIVISION.
       FILE SECTION.
       FD  CUST-FILE.
       01  CUST-REC.
           05  CUST-ID        PIC X(6).
           05  CUST-NAME      PIC X(20).
       WORKING-STORAGE SECTION.
       01  WS-EOF             PIC X VALUE "N".
           88  END-OF-FILE    VALUE "Y".
       01  WS-COUNT           PIC 9(3) VALUE 0.
       PROCEDURE DIVISION.
       0000-MAIN.
           OPEN INPUT CUST-FILE
           PERFORM 8000-READ-CUST
           PERFORM UNTIL END-OF-FILE
               ADD 1 TO WS-COUNT
               DISPLAY WS-COUNT ": " CUST-NAME
               PERFORM 8000-READ-CUST
           END-PERFORM
           CLOSE CUST-FILE
           DISPLAY "RECORDS READ: " WS-COUNT
           STOP RUN.

       8000-READ-CUST.
           READ CUST-FILE
               AT END SET END-OF-FILE TO TRUE
           END-READ.

With DD_CUSTIN pointing at a dataset holding

C00042GRACE HOPPER
C00107ALAN TURING

the output is

001: GRACE HOPPER
002: ALAN TURING
RECORDS READ: 002

Why read before the loop?

Look at the order: read once before the loop, then at the end of each pass process the record and read the next one. The loop test UNTIL END-OF-FILE then always looks at the result of the most recent READ, before anything touches the record.

  • An empty file works: the priming read hits end-of-file straight away, the loop body never runs, and the count is zero.
  • The last record is processed exactly once. The read after it sets the flag, and the loop stops before the (now meaningless) record area can be processed again.

Beginners often write the loop the other way round, with the READ at the top of the body. Then the pass that hits end-of-file still falls through to the processing code, and the last record gets counted twice.

One READ paragraph

Put the READ in its own paragraph (8000-READ-CUST) and PERFORM it from both places. There is then one place to add record counts, status checks or debugging, and the two reads can never drift apart.

The alternative: NOT AT END

You will also meet this style in existing code:

           PERFORM UNTIL END-OF-FILE
               READ CUST-FILE
                   AT END SET END-OF-FILE TO TRUE
                   NOT AT END PERFORM 1000-PROCESS
               END-READ
           END-PERFORM

It is correct too: the processing only happens on a successful read. Many shop standards prefer the priming read because the main loop reads as plain steps ("process this record, get the next"), and it scales better when you are reading two files in step, as you will in the match-merge lesson.

On the job

Batch programs are expected to report their control totals, such as records read and records written, at the end of the run. Operators and auditors compare them between job steps: if step 1 wrote 10,482 records and step 2 read 10,481, something is wrong. Count every read.

Your task

Write a payroll listing. The employee file is assigned to DD name EMPIN (line sequential). Each record is:

Field Picture Positions
EMP-ID X(5) 1–5
EMP-NAME X(20) 6–25
EMP-DEPT X(3) 26–28
EMP-SALARY 9(6)V99 29–36

For each employee display the ID, name and salary (via WS-SALARY-ED), separated by single spaces. After the last record display the number of employees and the total salary:

E0001 GRACE HOPPER          85000.00
E0002 ALAN TURING           72500.50
E0003 ADA LOVELACE          93000.00
EMPLOYEES: 003
PAYROLL:   250500.50

Use the priming-read pattern. The file may be empty.

fixed format
Run your program to see its output here. The first visible test's input and datasets are used.
Submit to grade your program against every test.