Book Read Free

Michael Coughlan

Page 20

by Beginning COBOL for Programmers-Apress (2014) (pdf)


  INPUT 

  

  

  OPEN OUTPUT InternalFileName …

  

  

  EXTEND

  Opening a file does not transfer any data to the record buffer; it simply provides access.

  Notes on the OPEN Statement

  When a file is opened for INPUT or EXTEND, the file must exist or the OPEN will fail.

  When a file is opened for INPUT, the Next Record Pointer is positioned at the beginning of the file. The Next Record Pointer is conceptual; it points to the position in the file where the file system will get or put the next record.

  When the file is opened for EXTEND, the Next Record Pointer is positioned after the last record in the file. This allows records to be appended to the file.

  When a file is opened for OUTPUT, it is created if it does not exist, and it is overwritten if it already exists.

  ■ Bug Alert although the ellipses after InternalFileName in the metalanguage indicate that it is possible to open a number of files with one OPEN statement, it is not advisable to do so. If an error is detected on opening a file and only one OPEN statement has been used to open all the files, the system will not be able to indicate which particular file is causing the problem. If all the files are opened separately, it will.

  The CLOSE Statement

  The metalanguage for the CLOSE statement is fairly simple:

  CLOSE InternalFilename …

  Notes

  Before the program terminates, you must make sure the program closes all the open files. Failure to do so may result in some data not being written to the file or users being prevented from accessing the file.

  Hard disk access is about a million times slower than RAM access (hard disk access times are measured in

  milliseconds, whereas RAM access is measured in nanoseconds: 1 millisecond = 1,000 microseconds = 1,000,000

  nanoseconds), so data is often cached in memory until a sufficient quantity of records have been accumulated to make the write to disk worthwhile. If the file is not closed, it is possible that these cached records will never be sent to the file.

  ■ Bug Alert the ellipses in the CLOSE metalanguage indicate that you may specify more than one file name. I advised against this for the OPEN statement; but because very few errors affect the CLOSE statement, the same advice does not hold. For convenience, you can often choose to close multiple files in one CLOSE statement.

  139

  Chapter 7 ■ IntroduCtIon to SequentIal FIleS

  The READ Statement

  Once the system has opened a file and made it available to the program, it is your responsibility to process it correctly.

  To process all the records in the file, the program has to transfer them, one record at a time, from the file to the file’s record buffer. The READ is provided for this purpose:

  READ InternalFilename [NEXT] RECORD

  [INTO Identifier]

  [AT END StatementBlock ]

  1

  [NOT AT END StatementBlock2]

  [END-READ]

  The READ statement copies a record occurrence (instance) from the file on backing storage and places it in the record buffer defined for it.

  Notes

  When the READ attempts to read a record from the file and encounters the end of file marker, the AT END is triggered and StatementBlock1 is executed. If the NOT AT END clause is specified then StatementBlock2 is executed.

  When the INTO clause is used, the data is read into the record buffer and then copied from there, to the Identifier, in one operation. This option creates two copies of the data: one in the record buffer and one in the Identifier. Using the INTO clause is equivalent to reading a record and then moving the contents of the record buffer to the Identifier.

  COBOL Detail

  ■

  Because AT END is an optional element, you might have wondered how the end-of-file condition can

  be detected in its absence. CoBol has a special kind of exception handler for files called declaratives. When declaratives are specified for a file, any file error—including the end-of-file condition, causes the code in the declaratives to execute.

  declaratives are an advanced topic that I address later in the book.

  How READ Works

  Listing 7-1 is a small program that simply reads the records in the employee file: employee.dat. The test data for the program is given in Figure 7-4. The effect on the data storage of running the program with this data is shown in Figure 7-5.

  Listing 7-1. Reading the Employee File

  IDENTIFICATION DIVISION.

  PROGRAM-ID. Listing7-1.

  AUTHOR. Michael Coughlan.

  ENVIRONMENT DIVISION.

  INPUT-OUTPUT SECTION.

  FILE-CONTROL.

  SELECT EmployeeFile ASSIGN TO "Employee.dat"

  ORGANIZATION IS LINE SEQUENTIAL.

  DATA DIVISION.

  FILE SECTION.

  FD EmployeeFile.

  01 EmployeeDetails.

  140

  Chapter 7 ■ IntroduCtIon to SequentIal FIleS

  88 EndOfEmployeeFile VALUE HIGH-VALUES.

  02 EmpSSN PIC 9(9).

  02 EmpName.

  03 EmpSurname PIC X(15).

  03 EmpForename PIC X(10).

  02 EmpDateOfBirth.

  03 EmpYOB PIC 9(4).

  03 EmpMOB PIC 99.

  03 EmpDOB PIC 99.

  02 EmpGender PIC X.

  PROCEDURE DIVISION.

  Begin.

  OPEN INPUT EmployeeFile

  READ EmployeeFile

  AT END SET EndOfEmployeeFile TO TRUE

  END-READ

  PERFORM UNTIL EndOfEmployeeFile

  READ EmployeeFile

  AT END SET EndOfEmployeeFile TO TRUE

  END-READ

  END-PERFORM

  CLOSE EmployeeFile

  STOP RUN.

  Figure 7-4. Employee.dat test data file

  Figure 7-5. Effect on data storage of reading each record in the file

  141

  Chapter 7 ■ IntroduCtIon to SequentIal FIleS

  The effect on the data storage each time the READ is executed is shown in Figure 7-5:

  • Read1 shows the effect of reading the first record. When the record is read from Employee.dat,

  it is copied into the EmployeeDetails area of storage as shown.

  • Read2 and Read3 show the results of reading the second and third records.

  • Read4 shows what happens when an attempt to read a fourth record is made. Because there

  is no fourth record, the AT END activates and the condition name EndOfEmployeeFile is set to

  TRUE. This condition name is defined on the whole record, and as a result the whole record is

  filled with HIGH-VALUES (represented here as the ◆ symbol).

  ■ Note Because of space constraints in this book, the various pieces of test data given obviously are not comprehensive enough to test any of the programs adequately. the test data is provided for the purposes of illustration only. You should create your own, more comprehensive test data if you want to test the programs.

  Of course, this program does not do anything practical. It reads the file but doesn’t do anything with the records it reads. Listing 7-2 tweaks the program a little so that it displays the name and date of birth of each employee in the file. Notice that I have chosen not to display the data items in the same order they are in in the record. The employee name is displayed in forename-surname order, and the date of birth is displayed in the standard U.S. order (month, day, year).

  Listing 7-2. Reading the Employee File and Displaying the Records

  IDENTIFICATION DIVISION.

  PROGRAM-ID. Listing7-2.

  AUTHOR. Michael Coughlan.

  ENVIRONMENT DIVISION.

  INPUT-OUTPUT SECTION.

  FILE-CONTROL.

  SELECT EmployeeFile ASSIGN TO "Employee.dat"

  ORGANIZATION IS LIN
E SEQUENTIAL.

  DATA DIVISION.

  FILE SECTION.

  FD EmployeeFile.

  01 EmployeeDetails.

  88 EndOfEmployeeFile VALUE HIGH-VALUES.

  02 EmpSSN PIC 9(9).

  02 EmpName.

  03 EmpSurname PIC X(15).

  03 EmpForename PIC X(10).

  02 EmpDateOfBirth.

  03 EmpYOB PIC 9(4).

  03 EmpMOB PIC 99.

  03 EmpDOB PIC 99.

  02 EmpGender PIC X.

  142

  Chapter 7 ■ IntroduCtIon to SequentIal FIleS

  PROCEDURE DIVISION.

  Begin.

  OPEN INPUT EmployeeFile

  READ EmployeeFile

  AT END SET EndOfEmployeeFile TO TRUE

  END-READ

  PERFORM UNTIL EndOfEmployeeFile

  DISPLAY EmpForename SPACE EmpSurname " - "

  EmpMOB "/" EmpDOB "/" EmpYOB

  READ EmployeeFile

  AT END SET EndOfEmployeeFile TO TRUE

  END-READ

  END-PERFORM

  CLOSE EmployeeFile

  STOP RUN.

  The WRITE Statement

  The WRITE statement is used to copy data from the record buffer (RAM) to the file on backing storage (tape, disk, or CD-ROM). To write data to a file, the data must be moved to the record buffer (declared in the file’s FD entry), and then the WRITE statement is used to send the contents of the record buffer to the file:

  WRITE RecordName [FROM Identifier]

  

  

  LINE 

  

  AdvanceNum

  

  

  

  LINES

  

  

  

  

  BE

   FORE

  

  

  

  

  

  ADVANCING MnemonicName

  

  

  

  

  

   AFTER

  

  

  

  P

   AGE

  

  

  

  

  

  

  

  

  

  

  

  

  When WRITE..FROM is used, the data contained in the Identifier is copied into the record buffer and is then written to the file. WRITE..FROM is the equivalent of a MOVE Identifier TO RecordName statement followed by a WRITE RecordName statement.

  ■ Note the full metalanguage for the sequential-file version of WRITE statement is given here, but I postpone discussion of the ADVANCING clause until later in the book. this clause is used when writing print files and is a bit more complicated than it appears on the surface. It is best discussed when considering files with multiple record types.

  Write a Record, Read a File

  You probably noticed that the metalanguage for the READ and WRITE statements indicates that while you read a file, you write a record. You may have wondered why there is this difference.

  So far, you have only seen files that contain one type of record. In the employee file, for example, there is only one type of employee record. But a file may contain a number of different types of record. For instance, if you wanted to update the employee file, you might have a file of transaction records containing both Employee Insertion records and Employee Deletion records. Although an Insertion record would have to contain all the fields in the employee record, a Deletion record would only need the Employee SSN.

  143

  Chapter 7 ■ IntroduCtIon to SequentIal FIleS

  The reason you read a file, not a record, is that until the record is in the buffer you cannot tell what type of record it is. You have to read the file and then look at the data in the buffer to see what type of record has been supplied. It is your responsibility to discover what type of record has been read into the buffer and then to take the appropriate actions.

  The reason you write a record instead of a file is that when the output file will contain multiple types of record, you have to specify which record type you want to write to the file.

  How WRITE works

  Suppose you want to add some records to the end of the employee file. To do so, you use this statement:

  OPEN EXTEND EmployeeFile

  This tells the system that you are going to add records to the end of the file. If you opened the file for OUTPUT, then Employee.dat would be replaced (overwritten) with a new version of the employee file.

  To write a record to the file, you place the data in the EmployeeDetails record buffer and then use the following statement:

  WRITE EmployeeDetails

  The example program fragment in Example 7-6 writes two records to the end of the employee file. Figure 7-6

  shows the interaction between the data in memory and the file on backing storage. The first MOVE statement places the record data in the record buffer, and the WRITE statement (Write1) copies it to the file. The second MOVE places the second record in the record buffer, and the WRITE (Write2) copies it to the file.

  Example 7-6. Writing Records to the End of a Sequential File

  PROCEDURE DIVISION.

  Begin.

  OPEN EXTEND EmployeeFile

  MOVE "456867564NEWGIRL MARTHA 19820712f"

  TO EmployeeDetails

  WRITE EmployeeDetails

  MOVE "622842649NEWBOY MALCOLM 19810925m"

  TO EmployeeDetails

  WRITE EmployeeDetails

  CLOSE EmployeeFile

  STOP RUN.

  144

  Chapter 7 ■ IntroduCtIon to SequentIal FIleS

  Figure 7-6. Writing two records to the employee file (see Example 7-6)

  Reading and Writing to the Employee File

  The program in Listing 7-3 extends the fragment in Example 7-3 into a full-blown program. However, whereas the data sent to the employee file in Example 7-3 was hard-coded in the form of literal values, in Listing 7-3 the records to be added to the file are obtained from the user. A very simple interface is used to get the records. A template for the record is displayed, and the user then enters the data based on the template. A screen capture shows the data requested from the user and then output when the file is read.

  Listing 7-3. Writing and Reading the Employee File

  IDENTIFICATION DIVISION.

  PROGRAM-ID. Listing7-3.

  AUTHOR. Michael Coughlan.

  ENVIRONMENT DIVISION.

  INPUT-OUTPUT SECTION.

  FILE-CONTROL.

  SELECT EmployeeFile ASSIGN TO "Employee.dat"

  ORGANIZATION IS LINE SEQUENTIAL.

  DATA DIVISION.

  FILE SECTION.

  FD EmployeeFile.

  01 EmployeeDetails.

  88 EndOfEmployeeFile VALUE HIGH-VALUES.

  02 EmpSSN PIC 9(9).

  02 EmpName.

  03 EmpSurname PIC X(15).

  03 EmpForename PIC X(10).

  145

  Chapter 7 ■ IntroduCtIon to SequentIal FIleS

  02 EmpDateOfBirth.

  03 EmpYOB PIC 9(4).

  03 EmpMOB PIC 99.

  03 EmpDOB PIC 99.

  02 EmpGender PIC X.

  PROCEDURE DIVISION.

  Begin.

  OPEN EXTEND EmployeeFile

  PERFORM GetEmployeeData

  PERFORM UNTIL EmployeeDetails = SPACES

  WRITE EmployeeDetails

  PERFORM GetEmployeeData

  END-PERFORM

  CLOSE EmployeeFile

  DISPLAY "************* End of Input ****************"

  OPEN INPUT EmployeeFile

  READ EmployeeFile

  AT END SET EndOfEmployeeFile TO TRUE

  END-READ

  PERFORM UNTIL EndOfEmployeeFi
le

  DISPLAY EmployeeDetails

  READ EmployeeFile

  AT END SET EndOfEmployeeFile TO TRUE

  END-READ

  END-PERFORM

  CLOSE EmployeeFile

  STOP RUN.

  GetEmployeeData.

  DISPLAY "nnnnnnnnnSSSSSSSSSSSSSSSFFFFFFFFFFyyyyMMddG"

  ACCEPT EmployeeDetails.

  Summary

  This chapter provided a gentle introduction to sequential files. You learned how to declare the record buffer for a file.

  You learned how to connect the file’s internal file name with its name and location on the backing storage device. You saw how to READ records from a file and how to WRITE them to a file.

  Although this chapter is a good start, there is still much more to discover about sequential files. Although I touched on the idea of files that contain multiple record types, I did not explore the full ramifications of this concept; nor did I discuss the true magic of the FILE SECTION. I mentioned print files, but I did not explore the relevant options in the metalanguage; nor did I discuss how to create a print file. I also have not mentioned or discussed the idea of variable-length records. I discussed some of the mechanics of using sequential files in this chapter, but I did not discuss sequential-file processing issues. The chapters that follow explore some of those issues by examining the control-break and file-update problems.

  146

  Chapter 7 ■ IntroduCtIon to SequentIal FIleS

  LaNGUaGe KNOWLeDGe eXerCISe

  unsheathe your 2B pencil. It is exercise time again.

  1. locate errors in these FILE SECTION entries.

  (a)

  FD SalesFile.

  01 SalesRecord PIC X(13).

  02 SalesmanNumber PIC 9(7).

  02 SaleValue PIC 9(5)V99.

  (b)

  FD TemperatureFile.

  01 DayRecord.

  05 MonthNumber PIC 99

  05 MaxTemp PIC 999

  05 MinTemp PIC 999

  06 AverageTemp PIC 999

  (c)

  FD StudentFile

  01 StudentRecord.

  02 StudentName. PIC X(20).

  05 StudentInitials PIC XX.

  05 StudnetSurname PIC X(18).

  02 StudentAddress PIC X(65).

  03 AddressLine1. PIC X(10).

  03 AddressLine2 PIC X(10)

 

‹ Prev