Search code examples
cobolmainframe

Buffer in cobol file handling


I have written a code to match the date given by user(instream data) with the date mentioned in an input file. When the date matches, the record is moved to an output file. The program ran successfully. Now i am inserting a header in output file by declaring a variable 'header' in working-storage section, moving the 'header' field to output record and writing the output record. Though it is running successfully i have a doubt. I looked for it everywhere but unable to find it. The problem is-

The concept of buffer tells us that while declaring File Description(FD) it creates a structure. The file description(FD) given with all the records and fields creates a buffer structure. Now all the read/write operation happens through it.
If a program processes more than one file, a record buffer must be defined for each file.

To process all the records in an INPUT file, we must ensure that each record instance is copied from the file, into the record buffer, when required.

To create an OUTPUT file containing data records, we must ensure that each record is placed in the record buffer and then transferred to the file.

To transfer a record from an input file to an output file we must read the record into the input record buffer, transfer it to the output record buffer and then write the data to the output file from the output record buffer.

So when i am giving the date separately and moving it to the output record it is SURELY not going into that buffer which i created using FD in output record. So how is it going there?? If it is creating its own buffer then all data can be moved directly, what is the need of declaring FD??

This is the link to see the concept of buffer
[1]: http://www.csis.ul.ie/cobol/course/SequentialFiles1.htm

This is my code as given below-
JUST EMPHASIZE ON STATEMENTS IN SLASHES

   IDENTIFICATION DIVISION.                      
   PROGRAM-ID. TXNRPT02 .                        
   ENVIRONMENT DIVISION.                         
   INPUT-OUTPUT SECTION.                         
   FILE-CONTROL.                                 
      SELECT D01-TXN-FILE ASSIGN TO DETLFILE    
      ORGANIZATION IS SEQUENTIAL                
      ACCESS MODE IS SEQUENTIAL                 
      FILE STATUS IS WS-INSERT-FILE-STATUS1.    

      SELECT D02-TXN-FILE ASSIGN TO DATEOUT     
      ORGANIZATION IS SEQUENTIAL                
      ACCESS MODE IS SEQUENTIAL                 
      FILE STATUS IS WS-INSERT-FILE-STATUS2.    
      DATA DIVISION.                                
      FILE SECTION.                           
        FD D01-TXN-FILE.    // CREATES A BUFFER                    
        01 D01-TXN-REC.                         
          05 TXN-DATE PIC 9(8).               
          05 FILLER PIC X(1).                 
          05 TXN-NUMBER PIC 9(5).             
          05 FILLER PIC X(1).                 
          05 SBACCT-CODE PIC 9(5).            
          05 FILLER PIC X(1).                 
          05 TXN-AMOUNT PIC 9(5)V9(2).        
          05 FILLER PIC X(52).                
        FD D02-TXN-FILE.                //CREATES A BUFFER STRUCTURE IN OUTPUT FILE        
        01 D02-TXN-REC.                         
          05 TXN-DATE1 PIC 9(8).              
          05 FILLER PIC X(1).                 
          05 TXN-NUMBER1 PIC 9(5).            
          05 FILLER PIC X(1).                 
          05 SBACCT-CODE1 PIC 9(5).           
          05 FILLER PIC X(1).                 
          05 TXN-AMOUNT1 PIC 9(5)V9(2).       
          05 FILLER PIC X(52).                
     WORKING-STORAGE SECTION.
       01 HEAD1                            // declaring header
          02 FILLER PIC X(20).
          02 TEXT PIC X(40) VALUE 'REPORT OF BANK'          
       01 FILE-STATUS PIC X(02) VALUE '00'.    
          88 EOF VALUE '10'.                  
          88 SUCCESS VALUE '00'.              
       01 WS-INSERT-FILE-STATUS1 PIC X(2).     
       01 WS-INSERT-FILE-STATUS2 PIC X(2).     
       01 WS-DATE PIC 9(8).              // DATE TO BE ACCEPTED FROM INSTREAM DATA      
   PROCEDURE DIVISION.                     
   MAIN-PARA.                              
       ACCEPT WS-DATE.                     
       PERFORM OPEN-PARA.                  
       PERFORM INIT-PARA.                  
       PERFORM PROCESS-PARA UNTIL EOF.     
       PERFORM CLOSE-PARA.                 
       STOP RUN.                           
  OPEN-PARA.                   // OPENS INPUT AND OUTPUT FILES                              
       OPEN INPUT D01-TXN-FILE.                               
       DISPLAY 'INFILE OPEN STATUS' , WS-INSERT-FILE-STATUS1. 
       OPEN OUTPUT D02-TXN-FILE.                              
       DISPLAY 'OUTFILE OPEN STATUS' ,WS-INSERT-FILE-STATUS2. 
 INIT-PARA.                    // INITIALIZES BOTH RECORDS                             
       INITIALIZE D01-TXN-REC.                                
       INITIALIZE D02-TXN-REC.                                
 PROCESS-PARA.                                              
        MOVE HEAD1 TO D02-TXN-REC.   // MOVING HEADER TO OUTPUT RECORD
          WRITE D02-TXN-REC.         // WRITING THE HEADER
                  READ D01-TXN-FILE                                      
                   AT END MOVE '10' TO FILE-STATUS      
             NOT AT END PERFORM OPPO-PARA               

      END-READ.                                              
 OPPO-PARA.                      //PERFORMS EQUAL OPERATION ON BOTH DATES                           
      IF WS-DATE = TXN-DATE                                  
     MOVE D01-TXN-REC TO D02-TXN-REC                        
     WRITE D02-TXN-REC                                      
     END-IF.                                                  
 CLOSE-PARA.                // CLOSING BOTH FILES                                  
     CLOSE D01-TXN-FILE, D02-TXN-FILE.                        
     DISPLAY 'INFILE CLOSE STATUS' , WS-INSERT-FILE-STATUS1.  
     DISPLAY 'OUTFILE CLOSE STATUS' , WS-INSERT-FILE-STATUS2. 

Solution

  • I think you are over-complicating things.

    In the FILE SECTION you logically connect a record-layout to a file that will be read, or to a record which will be written (to a file).

    No storage is allocated in your COBOL program by the definition of the FD or any 01-levels subordinate to an FD. You simply establish a "map" which will be used to understand the data read from a file, or to use to construct the data which you will write to a file.

    When you OPEN a file, some run-time code does that work behind the scenes, and will make the address of the first byte of your record layout(s) under the FD equal to the first byte of the piece of storage that will be used as the "buffer".

    A "buffer" in this context is just a piece of storage which is the same size as your BLKSIZE and which will be used, without you having to be aware of it, to store records before they are actually written to the physical output file.

    What happens when you WRITE a record is that the record-pointer simply gets changed to the first available byte after the current record.

    It is similar when you read.

    Although installation-dependent, mostly you will have the default number of buffers for a simple sequential file, which is five. Once a buffer is full the, for an output file, the IO-subsystem will be told it has data available for writing, and the filling will continue, asynchronously, with the next buffer area. What this does is reduce the amount of time your COBOL program is waiting for IO to complete.

    It is similar, which obvious reversals, for the READ of a sequential file.

    As a beginner, you don't need to know what the buffering is doing. Just keep it conceptually simple. You OPEN, you READ, the record is "under" the FD. You continue doing that until end-of-file, then you CLOSE. At the same time (usually) you OPEN, you WRITE, and you CLOSE at the end. What gets written is the data that is under the FD for the output file.

    Also review READ ... INTO ... and WRITE ... FROM .... The concept is the same, it is just that COBOL will "move" the data to the FD for you, rather than you having detailed record-layouts under the FD. Whether you use READ file or READ file INTO record-layout is usually down to local standards for your site - do it the way your team does it.

    You have now added some code to your Question.

    First thing, you are writing your header inside a loop. You will get one header per record, which is probably not what you want.

    Secondly, you've changed to use the FILE STATUS but not fully grasped how it works yet. You don't need the AT END/NOT AT END. The COBOL IO will maintain the FILE STATUS field. When end-of-file is identified by the COBOL run-time the FILE STATUS field will be set to "10", "automatically" as far as you are concerned.

    Thirdly, review your use of INITIALIZE. There is never any point in INITIALIZE on an input record. READ always advances the record-pointer. The storage INITIALIZEd is the storage before the record you read. Even if it was not, what is the point of INITIALIZE, just to read a record over the top of the initialised storage? Same with your output.

    All that your use of INITIALIZE is doing is using CPU time. Yes, it is not at all uncommon that this happens, but that is no excuse for you to pick up bad habits as well.