MainframeMaster

COBOL Tutorial

COBOL END-READ Statement

The END-READ statement represents a fundamental component of file processing operations in COBOL, serving as an explicit scope terminator that clearly defines the boundaries of READ statement blocks. This statement embodies modern file handling principles by providing unambiguous termination points for input operations, enabling sophisticated error handling for file access scenarios, and supporting the development of robust data processing applications that require precise control over file reading operations and exception management.

In contemporary enterprise COBOL development, END-READ plays a vital role in creating sophisticated file processing systems that must handle various file types, access methods, and error conditions. By providing explicit termination for READ blocks, this statement enables developers to implement comprehensive file processing logic while maintaining code clarity and ensuring that file operations are properly bounded and controlled within the application's data processing flow.

Basic END-READ Usage

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
IDENTIFICATION DIVISION. PROGRAM-ID. END-READ-DEMO. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT EMPLOYEE-FILE ASSIGN TO 'EMPLOYEES.DAT' ORGANIZATION IS SEQUENTIAL ACCESS MODE IS SEQUENTIAL FILE STATUS IS EMPLOYEE-FILE-STATUS. SELECT INDEXED-FILE ASSIGN TO 'INDEXED.DAT' ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS EMPLOYEE-ID FILE STATUS IS INDEXED-FILE-STATUS. DATA DIVISION. FILE SECTION. FD EMPLOYEE-FILE. 01 EMPLOYEE-RECORD. 05 EMPLOYEE-ID PIC X(10). 05 EMPLOYEE-NAME PIC X(30). 05 EMPLOYEE-SALARY PIC 9(7)V99. 05 EMPLOYEE-DEPARTMENT PIC X(15). FD INDEXED-FILE. 01 INDEXED-RECORD. 05 EMPLOYEE-ID PIC X(10). 05 EMPLOYEE-DATA PIC X(50). WORKING-STORAGE SECTION. 01 FILE-STATUS-CODES. 05 EMPLOYEE-FILE-STATUS PIC XX. 88 EMPLOYEE-FILE-OK VALUE '00'. 88 EMPLOYEE-FILE-EOF VALUE '10'. 88 EMPLOYEE-FILE-ERROR VALUE '01' THRU '09', '11' THRU '99'. 05 INDEXED-FILE-STATUS PIC XX. 88 INDEXED-FILE-OK VALUE '00'. 88 INDEXED-FILE-EOF VALUE '10'. 88 INDEXED-FILE-ERROR VALUE '01' THRU '09', '11' THRU '99'. 01 PROCESSING-COUNTERS. 05 RECORDS-READ PIC 9(7) VALUE 0. 05 SUCCESSFUL-READS PIC 9(7) VALUE 0. 05 FAILED-READS PIC 9(7) VALUE 0. 05 EOF-REACHED PIC X VALUE 'N'. 88 END-OF-FILE VALUE 'Y'. 01 SEARCH-CRITERIA. 05 SEARCH-ID PIC X(10). 05 FOUND-FLAG PIC X VALUE 'N'. 88 RECORD-FOUND VALUE 'Y'. 88 RECORD-NOT-FOUND VALUE 'N'. PROCEDURE DIVISION. MAIN-PROCESSING. PERFORM PROCESS-SEQUENTIAL-FILE PERFORM PROCESS-INDEXED-FILE PERFORM DISPLAY-STATISTICS STOP RUN. PROCESS-SEQUENTIAL-FILE. DISPLAY 'Processing sequential file...' OPEN INPUT EMPLOYEE-FILE IF NOT EMPLOYEE-FILE-OK DISPLAY 'Error opening employee file: ' EMPLOYEE-FILE-STATUS STOP RUN END-IF PERFORM READ-SEQUENTIAL-RECORDS CLOSE EMPLOYEE-FILE DISPLAY 'Sequential file processing completed'. READ-SEQUENTIAL-RECORDS. *> Read first record READ EMPLOYEE-FILE AT END DISPLAY 'File is empty' SET END-OF-FILE TO TRUE NOT AT END DISPLAY 'First record read successfully' ADD 1 TO RECORDS-READ ADD 1 TO SUCCESSFUL-READS PERFORM PROCESS-EMPLOYEE-RECORD END-READ *> Continue reading until end of file PERFORM UNTIL END-OF-FILE READ EMPLOYEE-FILE AT END DISPLAY 'End of file reached' SET END-OF-FILE TO TRUE NOT AT END ADD 1 TO RECORDS-READ *> Validate record before processing IF EMPLOYEE-ID NOT = SPACES AND EMPLOYEE-NAME NOT = SPACES ADD 1 TO SUCCESSFUL-READS PERFORM PROCESS-EMPLOYEE-RECORD ELSE ADD 1 TO FAILED-READS DISPLAY 'Invalid record found at position: ' RECORDS-READ END-IF END-READ END-PERFORM. PROCESS-EMPLOYEE-RECORD. DISPLAY 'Processing employee: ' EMPLOYEE-ID DISPLAY 'Name: ' EMPLOYEE-NAME DISPLAY 'Salary: ' EMPLOYEE-SALARY DISPLAY 'Department: ' EMPLOYEE-DEPARTMENT DISPLAY '---'. PROCESS-INDEXED-FILE. DISPLAY 'Processing indexed file...' OPEN I-O INDEXED-FILE IF NOT INDEXED-FILE-OK DISPLAY 'Error opening indexed file: ' INDEXED-FILE-STATUS STOP RUN END-IF PERFORM DEMONSTRATE-RANDOM-ACCESS PERFORM DEMONSTRATE-SEQUENTIAL-ACCESS CLOSE INDEXED-FILE DISPLAY 'Indexed file processing completed'. DEMONSTRATE-RANDOM-ACCESS. DISPLAY 'Demonstrating random access reads:' *> Search for specific records MOVE 'EMP001' TO SEARCH-ID PERFORM SEARCH-INDEXED-RECORD MOVE 'EMP005' TO SEARCH-ID PERFORM SEARCH-INDEXED-RECORD MOVE 'EMP999' TO SEARCH-ID PERFORM SEARCH-INDEXED-RECORD. SEARCH-INDEXED-RECORD. MOVE SEARCH-ID TO EMPLOYEE-ID SET RECORD-NOT-FOUND TO TRUE READ INDEXED-FILE KEY IS EMPLOYEE-ID INVALID KEY DISPLAY 'Record not found: ' SEARCH-ID SET RECORD-NOT-FOUND TO TRUE NOT INVALID KEY DISPLAY 'Record found: ' SEARCH-ID DISPLAY 'Data: ' EMPLOYEE-DATA SET RECORD-FOUND TO TRUE END-READ. DEMONSTRATE-SEQUENTIAL-ACCESS. DISPLAY 'Demonstrating sequential access on indexed file:' *> Start from beginning MOVE LOW-VALUES TO EMPLOYEE-ID START INDEXED-FILE KEY IS GREATER THAN EMPLOYEE-ID INVALID KEY DISPLAY 'No records to process' NOT INVALID KEY PERFORM READ-INDEXED-SEQUENTIALLY END-START. READ-INDEXED-SEQUENTIALLY. MOVE 'N' TO EOF-REACHED MOVE 0 TO RECORDS-READ PERFORM UNTIL END-OF-FILE OR RECORDS-READ >= 10 READ INDEXED-FILE NEXT AT END DISPLAY 'End of indexed file reached' SET END-OF-FILE TO TRUE NOT AT END ADD 1 TO RECORDS-READ DISPLAY 'Sequential read #' RECORDS-READ DISPLAY 'ID: ' EMPLOYEE-ID DISPLAY 'Data: ' EMPLOYEE-DATA END-READ END-PERFORM. DISPLAY-STATISTICS. DISPLAY 'File Processing Statistics:' DISPLAY 'Total records read: ' RECORDS-READ DISPLAY 'Successful reads: ' SUCCESSFUL-READS DISPLAY 'Failed reads: ' FAILED-READS IF RECORDS-READ > 0 COMPUTE SUCCESSFUL-READS = (SUCCESSFUL-READS / RECORDS-READ) * 100 DISPLAY 'Success rate: ' SUCCESSFUL-READS '%' END-IF.

Advanced END-READ Patterns

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
IDENTIFICATION DIVISION. PROGRAM-ID. ADVANCED-END-READ. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT TRANSACTION-FILE ASSIGN TO 'TRANSACTIONS.DAT' ORGANIZATION IS SEQUENTIAL ACCESS MODE IS SEQUENTIAL FILE STATUS IS TRANS-FILE-STATUS. SELECT MASTER-FILE ASSIGN TO 'MASTER.DAT' ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS ACCOUNT-NUMBER ALTERNATE RECORD KEY IS CUSTOMER-NAME WITH DUPLICATES FILE STATUS IS MASTER-FILE-STATUS. DATA DIVISION. FILE SECTION. FD TRANSACTION-FILE. 01 TRANSACTION-RECORD. 05 TRANS-TYPE PIC X(2). 05 ACCOUNT-NUMBER PIC X(12). 05 TRANS-AMOUNT PIC 9(9)V99. 05 TRANS-DATE PIC X(8). 05 TRANS-DESCRIPTION PIC X(30). FD MASTER-FILE. 01 MASTER-RECORD. 05 ACCOUNT-NUMBER PIC X(12). 05 CUSTOMER-NAME PIC X(30). 05 ACCOUNT-BALANCE PIC S9(11)V99. 05 ACCOUNT-STATUS PIC X(2). 05 LAST-ACTIVITY-DATE PIC X(8). WORKING-STORAGE SECTION. 01 FILE-STATUS-AREAS. 05 TRANS-FILE-STATUS PIC XX. 88 TRANS-FILE-OK VALUE '00'. 88 TRANS-FILE-EOF VALUE '10'. 88 TRANS-FILE-ERROR VALUE '01' THRU '09', '11' THRU '99'. 05 MASTER-FILE-STATUS PIC XX. 88 MASTER-FILE-OK VALUE '00'. 88 MASTER-FILE-EOF VALUE '10'. 88 MASTER-RECORD-NOT-FOUND VALUE '23'. 88 MASTER-FILE-ERROR VALUE '01' THRU '09', '11' THRU '22', '24' THRU '99'. 01 PROCESSING-CONTROLS. 05 BATCH-SIZE PIC 9(5) VALUE 1000. 05 CURRENT-BATCH PIC 9(5) VALUE 0. 05 RECORDS-IN-BATCH PIC 9(5) VALUE 0. 05 TOTAL-PROCESSED PIC 9(8) VALUE 0. 05 VALIDATION-ERRORS PIC 9(5) VALUE 0. 05 UPDATE-ERRORS PIC 9(5) VALUE 0. 01 TRANSACTION-VALIDATION. 05 VALID-TRANS-TYPES PIC X(10) VALUE 'DWCITF'. 05 CURRENT-TRANS-TYPE PIC X(2). 05 VALIDATION-RESULT PIC X VALUE 'N'. 88 TRANSACTION-VALID VALUE 'Y'. 88 TRANSACTION-INVALID VALUE 'N'. 01 ERROR-HANDLING. 05 ERROR-MESSAGE PIC X(80). 05 RETRY-COUNT PIC 9(2) VALUE 0. 05 MAX-RETRIES PIC 9(2) VALUE 3. 05 CONTINUE-PROCESSING PIC X VALUE 'Y'. 88 PROCESSING-ACTIVE VALUE 'Y'. 88 PROCESSING-STOPPED VALUE 'N'. PROCEDURE DIVISION. MAIN-PROCESSING. PERFORM INITIALIZE-PROCESSING PERFORM PROCESS-TRANSACTION-BATCHES PERFORM FINALIZE-PROCESSING STOP RUN. INITIALIZE-PROCESSING. DISPLAY 'Initializing transaction processing system...' OPEN INPUT TRANSACTION-FILE IF NOT TRANS-FILE-OK DISPLAY 'Fatal error opening transaction file: ' TRANS-FILE-STATUS STOP RUN END-IF OPEN I-O MASTER-FILE IF NOT MASTER-FILE-OK DISPLAY 'Fatal error opening master file: ' MASTER-FILE-STATUS CLOSE TRANSACTION-FILE STOP RUN END-IF DISPLAY 'Files opened successfully' DISPLAY 'Starting transaction processing...'. PROCESS-TRANSACTION-BATCHES. SET PROCESSING-ACTIVE TO TRUE PERFORM UNTIL PROCESSING-STOPPED PERFORM PROCESS-SINGLE-BATCH *> Check if we should continue processing IF TRANS-FILE-EOF SET PROCESSING-STOPPED TO TRUE DISPLAY 'All transactions processed' ELSE IF VALIDATION-ERRORS > 100 SET PROCESSING-STOPPED TO TRUE DISPLAY 'Too many validation errors - stopping' END-IF END-IF END-PERFORM. PROCESS-SINGLE-BATCH. ADD 1 TO CURRENT-BATCH MOVE 0 TO RECORDS-IN-BATCH DISPLAY 'Processing batch: ' CURRENT-BATCH PERFORM UNTIL RECORDS-IN-BATCH >= BATCH-SIZE OR TRANS-FILE-EOF PERFORM READ-AND-VALIDATE-TRANSACTION IF TRANSACTION-VALID PERFORM PROCESS-VALID-TRANSACTION ELSE PERFORM HANDLE-INVALID-TRANSACTION END-IF END-PERFORM DISPLAY 'Batch ' CURRENT-BATCH ' completed' DISPLAY 'Records in batch: ' RECORDS-IN-BATCH DISPLAY 'Total processed: ' TOTAL-PROCESSED. READ-AND-VALIDATE-TRANSACTION. MOVE 'N' TO VALIDATION-RESULT READ TRANSACTION-FILE AT END DISPLAY 'End of transaction file reached' SET TRANS-FILE-EOF TO TRUE NOT AT END ADD 1 TO RECORDS-IN-BATCH ADD 1 TO TOTAL-PROCESSED *> Validate transaction type MOVE TRANS-TYPE TO CURRENT-TRANS-TYPE IF CURRENT-TRANS-TYPE = 'DW' OR 'CR' OR 'IT' OR 'FT' *> Validate account number format IF ACCOUNT-NUMBER NOT = SPACES AND ACCOUNT-NUMBER NOT = LOW-VALUES *> Validate amount IF TRANS-AMOUNT > 0 SET TRANSACTION-VALID TO TRUE ELSE MOVE 'Invalid transaction amount' TO ERROR-MESSAGE END-IF ELSE MOVE 'Invalid account number' TO ERROR-MESSAGE END-IF ELSE MOVE 'Invalid transaction type' TO ERROR-MESSAGE END-IF END-READ. PROCESS-VALID-TRANSACTION. *> Read corresponding master record MOVE ACCOUNT-NUMBER TO ACCOUNT-NUMBER OF MASTER-RECORD READ MASTER-FILE KEY IS ACCOUNT-NUMBER INVALID KEY DISPLAY 'Master record not found: ' ACCOUNT-NUMBER ADD 1 TO VALIDATION-ERRORS MOVE 'Account not found' TO ERROR-MESSAGE PERFORM LOG-TRANSACTION-ERROR NOT INVALID KEY PERFORM UPDATE-MASTER-RECORD END-READ. UPDATE-MASTER-RECORD. EVALUATE TRANS-TYPE WHEN 'DW' *> Debit/Withdrawal IF ACCOUNT-BALANCE >= TRANS-AMOUNT SUBTRACT TRANS-AMOUNT FROM ACCOUNT-BALANCE PERFORM REWRITE-MASTER-RECORD ELSE DISPLAY 'Insufficient funds for account: ' ACCOUNT-NUMBER ADD 1 TO UPDATE-ERRORS END-IF WHEN 'CR' *> Credit/Deposit ADD TRANS-AMOUNT TO ACCOUNT-BALANCE PERFORM REWRITE-MASTER-RECORD WHEN 'IT' *> Interest Transaction COMPUTE ACCOUNT-BALANCE = ACCOUNT-BALANCE + (ACCOUNT-BALANCE * (TRANS-AMOUNT / 10000)) PERFORM REWRITE-MASTER-RECORD WHEN 'FT' *> Fee Transaction SUBTRACT TRANS-AMOUNT FROM ACCOUNT-BALANCE PERFORM REWRITE-MASTER-RECORD WHEN OTHER DISPLAY 'Unhandled transaction type: ' TRANS-TYPE ADD 1 TO UPDATE-ERRORS END-EVALUATE. REWRITE-MASTER-RECORD. MOVE TRANS-DATE TO LAST-ACTIVITY-DATE REWRITE MASTER-RECORD INVALID KEY DISPLAY 'Error updating master record: ' ACCOUNT-NUMBER DISPLAY 'File status: ' MASTER-FILE-STATUS ADD 1 TO UPDATE-ERRORS NOT INVALID KEY DISPLAY 'Account updated: ' ACCOUNT-NUMBER DISPLAY 'New balance: ' ACCOUNT-BALANCE END-REWRITE. HANDLE-INVALID-TRANSACTION. ADD 1 TO VALIDATION-ERRORS DISPLAY 'Invalid transaction found:' DISPLAY 'Type: ' TRANS-TYPE DISPLAY 'Account: ' ACCOUNT-NUMBER DISPLAY 'Amount: ' TRANS-AMOUNT DISPLAY 'Error: ' ERROR-MESSAGE PERFORM LOG-TRANSACTION-ERROR. LOG-TRANSACTION-ERROR. *> In a real system, this would write to an error log file DISPLAY 'ERROR LOG: ' ERROR-MESSAGE DISPLAY 'Transaction: ' TRANS-TYPE ' ' ACCOUNT-NUMBER ' ' TRANS-AMOUNT. FINALIZE-PROCESSING. CLOSE TRANSACTION-FILE CLOSE MASTER-FILE DISPLAY 'Transaction processing completed' DISPLAY 'Statistics:' DISPLAY 'Total batches processed: ' CURRENT-BATCH DISPLAY 'Total transactions: ' TOTAL-PROCESSED DISPLAY 'Validation errors: ' VALIDATION-ERRORS DISPLAY 'Update errors: ' UPDATE-ERRORS IF TOTAL-PROCESSED > 0 COMPUTE VALIDATION-ERRORS = ((TOTAL-PROCESSED - VALIDATION-ERRORS - UPDATE-ERRORS) / TOTAL-PROCESSED) * 100 DISPLAY 'Success rate: ' VALIDATION-ERRORS '%' END-IF.

Best Practices and FAQ

Best Practices
  • • Always use END-READ with conditional processing
  • • Implement proper file status checking
  • • Handle both AT END and NOT AT END conditions
  • • Use meaningful error messages
  • • Validate data after reading
Common Mistakes
  • • Omitting END-READ in complex structures
  • • Not handling file status conditions
  • • Poor error handling implementation
  • • Missing data validation after reads
  • • Inefficient file access patterns