COBOLMainframe

COBOL File Handling: OPEN, READ, WRITE, REWRITE, and CLOSE

TT
TopicTrick
COBOL File Handling: OPEN, READ, WRITE, REWRITE, and CLOSE

File I/O is at the heart of COBOL's purpose. Every batch job processes input files, updates master files, and writes output — all through COBOL's structured file handling verbs. Understanding the full lifecycle from SELECT through CLOSE, and the difference between sequential and random access patterns, is essential for production mainframe development.

File Declaration: SELECT and FD

Every file used by a program must be declared in two places: the SELECT statement in the FILE-CONTROL section of the ENVIRONMENT DIVISION, and an FD (File Description) entry in the FILE SECTION of the DATA DIVISION.

Sequential File (QSAM)

cobol
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT TRANSACTION-FILE
        ASSIGN TO TRANSIN
        ORGANIZATION IS SEQUENTIAL
        ACCESS MODE IS SEQUENTIAL
        FILE STATUS IS WS-TRAN-STATUS.

DATA DIVISION.
FILE SECTION.
FD  TRANSACTION-FILE
    RECORDING MODE IS F
    BLOCK CONTAINS 0 RECORDS
    RECORD CONTAINS 80 CHARACTERS.
01  TRANSACTION-RECORD       PIC X(80).

ASSIGN TO TRANSIN connects the logical file name to the JCL DD statement named TRANSIN. The physical dataset path is specified in JCL — the COBOL program never knows the actual dataset name, only the ddname.

RECORDING MODE IS F means fixed-length records. FB (fixed blocked) is specified in JCL; the COBOL compiler sees F. BLOCK CONTAINS 0 tells the runtime to use the block size from the JCL DD statement or dataset label.

VSAM KSDS File (Random Access)

cobol
FILE-CONTROL.
    SELECT CUSTOMER-MASTER
        ASSIGN TO CUSTMST
        ORGANIZATION IS INDEXED
        ACCESS MODE IS DYNAMIC
        RECORD KEY IS CM-CUSTOMER-ID
        ALTERNATE RECORD KEY IS CM-SSN
            WITH DUPLICATES
        FILE STATUS IS WS-CUST-STATUS.

FD  CUSTOMER-MASTER
    RECORD CONTAINS 200 CHARACTERS.
01  CUSTOMER-MASTER-RECORD.
    05 CM-CUSTOMER-ID    PIC X(10).
    05 CM-SSN            PIC X(11).
    05 CM-LAST-NAME      PIC X(25).
    05 CM-FIRST-NAME     PIC X(15).
    05 CM-BALANCE        PIC S9(11)V99 COMP-3.
    05 CM-STATUS         PIC X(2).
    05 CM-OPEN-DATE      PIC 9(8).
    05 FILLER            PIC X(110).

ORGANIZATION IS INDEXED defines a KSDS. ACCESS MODE IS DYNAMIC enables both sequential and random access within the same program. RECORD KEY IS CM-CUSTOMER-ID names the primary key — it must be a field within the FD record. ALTERNATE RECORD KEY provides a secondary access path.

FILE STATUS Codes

Always declare a FILE STATUS field and check it after every file operation:

cobol
WORKING-STORAGE SECTION.
01 WS-FILE-STATUSES.
   05 WS-CUST-STATUS    PIC XX VALUE SPACES.
      88 CUST-OK                  VALUE '00'.
      88 CUST-EOF                 VALUE '10'.
      88 CUST-NOT-FOUND           VALUE '23'.
      88 CUST-DUP-KEY             VALUE '22'.
      88 CUST-LOCKED              VALUE '9D'.
      88 CUST-OPEN-ERR  VALUE '90' '91' '92' '93' '94' '95'.

Key FILE STATUS codes:

CodeMeaning
00Successful completion
02Duplicate alternate key (non-fatal on READ)
10End of file reached
22Duplicate primary key on WRITE
23Record not found on random READ/DELETE
24Boundary violation (WRITE past end of relative file)
30Permanent I/O error
9DRecord locked by another task
9xVSAM-specific error — check VSAM return/reason codes

OPEN

Files must be opened before any I/O. The mode determines what operations are permitted:

cobol
OPEN INPUT  TRANSACTION-FILE.     *> read-only
OPEN OUTPUT REPORT-FILE.          *> write only (creates/replaces)
OPEN I-O    CUSTOMER-MASTER.      *> read and update (REWRITE/DELETE)
OPEN EXTEND AUDIT-LOG-FILE.       *> append to end of sequential file

IF NOT CUST-OK
    DISPLAY 'OPEN FAILED: ' WS-CUST-STATUS
    PERFORM ABEND-OPEN-FAILURE
END-IF.

Multiple files can be opened in a single statement:

cobol
OPEN INPUT  CUSTOMER-FILE
            PRODUCT-FILE
     OUTPUT REPORT-FILE.

Always check FILE STATUS immediately after OPEN. A 9x status on OPEN means the file is unavailable, misallocated, or the DD statement is missing — the program cannot proceed.

READ: Sequential

For sequential access, READ retrieves the next record in order:

cobol
READ-NEXT-RECORD.
    READ CUSTOMER-MASTER
        AT END SET CUST-EOF TO TRUE
        NOT AT END PERFORM PROCESS-CUSTOMER-RECORD
    END-READ.

The INTO phrase copies the record into a working-storage area (recommended for structured access):

cobol
READ TRANSACTION-FILE INTO WS-TRANSACTION-WORK
    AT END SET TRAN-EOF TO TRUE
END-READ.

Without INTO, the data is available in the FD record area directly. Using INTO gives you a working-storage copy with full COMP-3 field access.

READ: Random

Random READ retrieves a specific record by key:

cobol
RANDOM-READ-CUSTOMER.
    MOVE WS-SEARCH-ID TO CM-CUSTOMER-ID
    READ CUSTOMER-MASTER
    EVALUATE TRUE
        WHEN CUST-OK
            PERFORM PROCESS-FOUND-CUSTOMER
        WHEN CUST-NOT-FOUND
            MOVE 'CUSTOMER NOT ON FILE' TO WS-MESSAGE
            SET WS-ERROR-FOUND TO TRUE
        WHEN CUST-LOCKED
            PERFORM HANDLE-RECORD-LOCKED
        WHEN OTHER
            PERFORM HANDLE-READ-ERROR
    END-EVALUATE.

Move the key value to the RECORD KEY field in the FD record before issuing the READ. The runtime uses that value to locate the record.

READ with Alternate Key

cobol
MOVE WS-SSN TO CM-SSN
READ CUSTOMER-MASTER KEY IS CM-SSN
    INVALID KEY
        PERFORM HANDLE-SSN-NOT-FOUND
    NOT INVALID KEY
        PERFORM PROCESS-FOUND-RECORD
END-READ.

INVALID KEY is the older form of AT END/NOT AT END for keyed reads. Modern code prefers checking FILE STATUS via 88-level conditions.

READ: Sequential Browsing of VSAM (START + READ NEXT)

With ACCESS MODE IS DYNAMIC, you can position to a key and read sequentially from that point:

cobol
BROWSE-FROM-KEY.
    MOVE WS-START-ID TO CM-CUSTOMER-ID
    START CUSTOMER-MASTER
        KEY >= CM-CUSTOMER-ID
    IF NOT CUST-OK
        PERFORM HANDLE-START-ERROR
        EXIT PARAGRAPH
    END-IF

    PERFORM UNTIL CUST-EOF OR WS-BROWSE-DONE
        READ CUSTOMER-MASTER NEXT
            AT END SET CUST-EOF TO TRUE
        END-READ
        IF CUST-OK
            PERFORM PROCESS-BROWSE-RECORD
        END-IF
    END-PERFORM.

START positions the file cursor without reading a record. READ NEXT (or READ ... NEXT RECORD) then reads sequentially from that position.

WRITE

WRITE adds a new record to an output or I-O file:

cobol
*> Sequential output:
MOVE WS-REPORT-LINE TO REPORT-RECORD
WRITE REPORT-RECORD
    AFTER ADVANCING 1 LINE.

*> VSAM random write:
MOVE WS-NEW-CUSTOMER-DATA TO CUSTOMER-MASTER-RECORD
WRITE CUSTOMER-MASTER-RECORD
    INVALID KEY
        MOVE 'DUPLICATE CUSTOMER ID' TO WS-ERROR-MSG
        SET WS-ERROR-FOUND TO TRUE
    NOT INVALID KEY
        ADD 1 TO WS-RECORDS-WRITTEN
END-WRITE.

AFTER ADVANCING n LINES controls printer spacing for report files. AFTER ADVANCING PAGE issues a form feed.

INVALID KEY fires when a duplicate primary key exists. Always handle it — a duplicate write to a KSDS without error handling silently fails and raises FILE STATUS 22.

REWRITE

REWRITE updates an existing record in place. For sequential files, it replaces the last record returned by READ. For VSAM random access, it replaces the record matching the current key:

cobol
UPDATE-CUSTOMER-BALANCE.
    MOVE WS-ACCOUNT-ID TO CM-CUSTOMER-ID
    READ CUSTOMER-MASTER
    IF CUST-NOT-FOUND
        PERFORM HANDLE-NOT-FOUND
    ELSE IF CUST-OK
        ADD WS-TRANSACTION-AMOUNT TO CM-BALANCE
        REWRITE CUSTOMER-MASTER-RECORD
        IF NOT CUST-OK
            PERFORM HANDLE-REWRITE-ERROR
        END-IF
    END-IF.

The sequence is always: READ → modify fields in the record area → REWRITE. Attempting REWRITE without a prior successful READ produces unpredictable results.

DELETE

DELETE removes a record from a VSAM file. For KSDS files opened I-O, DELETE requires a prior READ:

cobol
CLOSE-CUSTOMER-ACCOUNT.
    MOVE WS-ACCOUNT-TO-CLOSE TO CM-CUSTOMER-ID
    READ CUSTOMER-MASTER
    IF CUST-OK
        DELETE CUSTOMER-MASTER RECORD
        IF NOT CUST-OK
            PERFORM HANDLE-DELETE-ERROR
        END-IF
    END-IF.

CLOSE

Always close files before the program ends:

cobol
FINALIZE-PROGRAM.
    CLOSE CUSTOMER-MASTER
          TRANSACTION-FILE
          REPORT-FILE.

Failing to CLOSE leaves enqueue locks on VSAM files, preventing other jobs from accessing them. On z/OS, abnormal program termination (ABEND) automatically releases locks, but a normal STOP RUN without CLOSE leaves files open.

Complete Batch Update Example

cobol
PROCEDURE DIVISION.

MAIN-LOGIC.
    PERFORM OPEN-ALL-FILES
    PERFORM READ-FIRST-TRANSACTION
    PERFORM UPDATE-LOOP UNTIL TRAN-EOF
    PERFORM CLOSE-ALL-FILES
    PERFORM DISPLAY-TOTALS
    STOP RUN.

OPEN-ALL-FILES.
    OPEN INPUT  TRANSACTION-FILE
    OPEN I-O    CUSTOMER-MASTER
    OPEN OUTPUT EXCEPTION-REPORT
    IF NOT TRAN-OK OR NOT CUST-OK OR NOT EXCPT-OK
        DISPLAY 'OPEN FAILED - TERMINATING'
        STOP RUN
    END-IF.

UPDATE-LOOP.
    MOVE WS-TRAN-ACCOUNT-ID TO CM-CUSTOMER-ID
    READ CUSTOMER-MASTER
    EVALUATE TRUE
        WHEN CUST-NOT-FOUND
            PERFORM WRITE-EXCEPTION-NOT-FOUND
        WHEN CUST-OK
            PERFORM APPLY-TRANSACTION
            PERFORM REWRITE-CUSTOMER
        WHEN OTHER
            PERFORM WRITE-EXCEPTION-IO-ERROR
    END-EVALUATE
    PERFORM READ-NEXT-TRANSACTION.

APPLY-TRANSACTION.
    ADD WS-TRAN-AMOUNT TO CM-BALANCE
    ADD 1 TO WS-UPDATES-APPLIED.

REWRITE-CUSTOMER.
    REWRITE CUSTOMER-MASTER-RECORD
    IF NOT CUST-OK
        PERFORM WRITE-EXCEPTION-REWRITE-ERROR
        SUBTRACT WS-TRAN-AMOUNT FROM CM-BALANCE
    END-IF.

CLOSE-ALL-FILES.
    CLOSE TRANSACTION-FILE
          CUSTOMER-MASTER
          EXCEPTION-REPORT.

Next Steps

File handling gives you the ability to read and update persistent data. The next capability is table handling — OCCURS, SEARCH, and INDEXED BY for in-memory arrays and lookup tables. See COBOL Table Handling, or return to the COBOL Mastery course.