COBOL:当两者都有 return 代码 10 时,如何区分文件结尾和垃圾值?

COBOL: How to differentiate between end of file and junk value when both have return code 10?

我正在使用 Fujitsu COBOL,在这种情况下我必须读取文件,如果有垃圾值,那么我想中止工作。

当存在垃圾值时,return 代码为 10,但要注意的是,即使存在 EOF(文件结尾),return 代码也为 10。

请帮助我如何根据 return 代码区分这两个事件?

在下面的代码中,我刚刚展示了一种区分文件状态代码为 10 的文件结尾和垃圾值的方法。

在程序中,正在读取一个文件。 FILE STATUS 正在读取的输入文件是 WS-ST。记录布局只是 1 个名为 NAME1 的字段。我不太确定垃圾值(在您的情况下)如何导致 FILE STATUS 具有 10 作为值。但是,为了重现您面临的错误,只要 NAME1 字段具有 SRINIVASAN 作为值,我就将 10 移至 WS-ST。当 NAME1 得到 SRINIVASAN 时,我还打破了 READ 循环。

READ循环之后,正在检查FILE STATUS数据项。如果它持有 10,则发出另一个 READ。在这里,我刚刚遇到 FILE STATUS 46.

46 - A sequential READ operation has been tried on a file open in the INPUT or I-O mode but no valid next record has been established.

处理 FILE STATUS 46 真正让您知道文件是否真的已结束。通过这种方式,您当然可以将 EOF 与垃圾价值区分开来。请仔细阅读此答案底部的示例,您可能会有所了解。

ID DIVISION.                                        
PROGRAM-ID. EOF1.                                   

ENVIRONMENT DIVISION.                               
INPUT-OUTPUT SECTION.                               
FILE-CONTROL.                                       
    SELECT INDD ASSIGN TO INDD                      
    FILE STATUS IS WS-ST.                           

DATA DIVISION.                                      
FILE SECTION.                                       
FD INDD.                                            
01 NAME1 PIC X(10).                                 
WORKING-STORAGE SECTION.                            
01 WS-ST   PIC 9(2) VALUE 0.                        
01 WS-READ PIC 9(2) VALUE 0.                        
01 WS-SWITCHES.                                     
   05 INDD-END    PIC X(1) VALUE 'N'.               
      88 INDD-EOF          VALUE 'Y'.               

PROCEDURE DIVISION.                                 
    OPEN INPUT INDD.                                
    PERFORM 100-READ THRU 100-EXIT UNTIL INDD-EOF.  
    IF WS-ST EQUAL 10                               
    READ INDD                                       
    DISPLAY 'READ FILE STATUS: ' WS-ST              
       IF WS-ST EQUAL 46                            
       DISPLAY 'END OF FILE'                        
       ELSE                                         
       DISPLAY 'RECORD' WS-READ ' IS ERRORED!'      
       MOVE 16 TO RETURN-CODE                       
       CLOSE INDD                                   
       STOP RUN                                     
       END-IF                                       
    ELSE                                            
    ADD 1 TO WS-READ                                
    END-IF.                                         
    CLOSE INDD.                                     
    STOP RUN.                                       

 100-READ.                                          
    READ INDD                                       
    AT END                                          
    SET INDD-EOF TO TRUE                            
    GO TO 100-EXIT                                  
    END-READ.                                       
    ADD 1 TO WS-READ.                               
    DISPLAY 'READ FILE STATUS: ' WS-ST.             
    DISPLAY 'RECORD' WS-READ ': ' NAME1.            
    IF NAME1 EQUAL 'SRINIVASAN'                     
    MOVE 10 TO WS-ST                                
    SET INDD-EOF TO TRUE                            
    END-IF.                                         
 100-EXIT. EXIT.

输入和输出的几个示例如下所示:

示例 1:

输入:第三条记录有误。

***************************** Top of Data ******************************
BHUTAN                                                                  
NEPAL                                                                   
SRINIVASAN                                                              
**************************** Bottom of Data ****************************

输出:程序以 RC 16 结束。程序没有进一步读取。

********************************* TOP OF DATA **********************************
RECORD01: BHUTAN                                                                
RECORD02: NEPAL                                                                 
RECORD03: SRINIVASAN                                                            
RECORD03 IS ERRORED!                                                            
******************************** BOTTOM OF DATA ********************************

示例 2:

输入:这次没有错误记录。

***************************** Top of Data ******************************
BHUTAN                                                                  
NEPAL                                                                   
**************************** Bottom of Data ****************************

输出:程序正常结束。 RC 00。

********************************* TOP OF DATA **********************************
RECORD01: BHUTAN                                                                
RECORD02: NEPAL                                                                 
END OF FILE                                                                     
******************************** BOTTOM OF DATA ********************************

示例 3:

输入:错误记录 SRINIVASANBHUTANNEPAL 之间。可能在这两个国家的边界​​上:) ?

***************************** Top of Data ******************************
BHUTAN                                                                  
SRINIVASAN                                                              
NEPAL                                                                   
**************************** Bottom of Data ****************************

输出:程序以 RC 16 结束。程序没有读取第 3 条记录,因为第 2 条记录出错。

********************************* TOP OF DATA **********************************
RECORD01: BHUTAN                                                                
RECORD02: SRINIVASAN                                                            
RECORD02 IS ERRORED!                                                            
******************************** BOTTOM OF DATA ********************************

示例 4:

输入:空输入文件

输出:程序正常结束。

********************************* TOP OF DATA **********************************
END OF FILE                                                                     
******************************** BOTTOM OF DATA ********************************

希望对您有所帮助!

在非常早期的 PC (MS-DOS 1.0) 上,Ctrl+Z (X"1A") 被用作文本文件的文件结尾。您的编译器可能会检测到该字符并将其视为 end-if-file 而不是允许处理文件的其余部分。

在OEM/DOS字符集中,X"1A"显示为右向箭头。 (你在评论中提到了一个箭头。)我创建了一个包含四个记录的短文件用于测试。

原文件:

Record1
Record2
Record3
Record4

我用 X"1A" 替换了 "3"。在十六进制编辑器中,它显示为,

请注意 x"1A" 字符显示为右向箭头。

A 编写了一个程序(未显示)来读取显示修改文件输出的文件。

Record1
Record2
Record
0003 lines read

文件结束出现在 X"1A"。

以下程序可用于检查 X"1A" 和 "identify the corrupt record occurrence ... so that [you] can correct the file"。

   program-id. ctrl-z.
   environment division.
   input-output section.
   file-control.
       select in-file assign "ctrl-z.txt"
           organization sequential
       .
   data division.
   file section.
   fd in-file.
   1 in-char pic x.
   working-storage section.
   1 line-count binary pic 9(4) value 0.
   1 msg-txt pic x(25) value "lines read".
     88 error-msg value "lines read before cntrl-z".
   1 eof-in-file-flag pic 9 value 0.
     88 eof-in-file value 1.
   procedure division.
   begin.
       open input in-file
       read in-file
           at end set eof-in-file to true
       end-read
       perform until eof-in-file
           evaluate in-char
           when x"0A"
               add 1 to line-count
           when x"1A"
               set error-msg to true
               set eof-in-file to true
               exit perform
           when other
               continue
           end-evaluate
           read in-file
               at end set eof-in-file to true
           end-read
       end-perform
       close in-file
       display line-count space msg-txt
       stop run
       .
   end program ctrl-z.

结果是:

0002 lines read before cntrl-z