使用 COBOL 从 .dat 文件中获取特定条目
Get specific entries from .dat file with COBOL
我是 COBOL 新手,在 .dat 文件中搜索特定条目时遇到问题。
这个想法是在文件中搜索在其中一个字段中具有特定代码的所有记录。
我试图在 google 中找到答案,但无论我走到哪里,答案都是不同的,我不知道为什么我不能使它们适应我的问题。
我也发现了这个问题:
How to insert records in a table in a text file using COBOL and search and display record(s) which satisfy a condition?
但答案不详
这是我的代码:
IDENTIFICATION DIVISION.
program-id. AR AS "A.AR".
environment division.
configuration section.
special-names. DECIMAL-POINT IS COMMA.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT ARQ-ATUALIZACAO ASSIGN "C:\temp\atualizacao.dat"
ORGANIZATION IS INDEXED
ACCESS MODE IS SEQUENTIAL
RECORD KEY IS ID-ATUALIZACAO
ALTERNATE RECORD KEY IS COD-RASTREIO
FILE STATUS IS ST-ATUALIZACAO.
data division.
FILE SECTION.
FD ARQ-ATUALIZACAO.
01 REG-ATUALIZACAO.
05 ID-ATUALIZACAO PIC 9(10).
05 COD-RASTREIO PIC X(13).
05 TITULO PIC X(15).
05 DESCRICAO PIC X(30).
05 FILLER PIC X(30).
working-storage section.
01 WS-RECORD.
03 ENTRIES OCCURS 18 TIMES INDEXED BY I.
05 WS-ID PIC 9(10).
05 WS-RAST PIC X(13).
05 WS-TIT PIC X(15).
05 WS-DESC PIC X(30).
77 ARE-THERE-MORE-RECORDS PIC XXX VALUE "YES".
77 NAME-COUNT PIC 99.
77 PROCURA PIC X(13).
77 ST-ATUALIZACAO PIC XX VALUE SPACES.
procedure division.
OPEN INPUT ARQ-ATUALIZACAO
PERFORM UNTIL ARE-THERE-MORE-RECORDS = 'NO '
READ ARQ-ATUALIZACAO
AT END
MOVE 'NO ' TO ARE-THERE-MORE-RECORDS
NOT AT END
PERFORM 300-STORE-NAME
END-READ
END-PERFORM
CLOSE ARQ-ATUALIZACAO.
300-STORE-NAME.
ADD 1 TO NAME-COUNT
MOVE REG-ATUALIZACAO TO ENTRIES OF WS-RECORD(NAME-COUNT).
OPEN I-O ARQ-ATUALIZACAO
DISPLAY "CODIGO DA ENCOMENDA.:" AT 1010
DISPLAY "STATUS:" AT 2433
DISPLAY ST-ATUALIZACAO AT 2440
ACCEPT PROCURA AT 1030 WITH REQUIRED FULL
SEARCH ENTRIES
AT END DISPLAY "CODIGO NAO ENCONTRADO" AT 0210
WHEN WS-RAST(I) = PROCURA
DISPLAY "REGISTROS ENCONTRADOS" AT 0210
DISPLAY WS-RAST(I) AT 0310
DISPLAY WS-ID(I) AT 0410
DISPLAY WS-TIT(I) AT 0510
DISPLAY WS-DESC(I) AT 0610
END-SEARCH
CLOSE ARQ-ATUALIZACAO
EXIT PROGRAM.
编辑 - 我更改了很多代码,所以我将 post 新代码放在这里:
IDENTIFICATION DIVISION.
program-id. ATUALIZACAOR AS "ATUALIZACAO.ATUALIZACAOR".
environment division.
configuration section.
special-names. DECIMAL-POINT IS COMMA.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT ARQ-ATUALIZACAO ASSIGN "C:\temp\atualizacao.dat"
ORGANIZATION IS INDEXED
RECORD KEY IS ID-ATUALIZACAO
ALTERNATE RECORD KEY IS COD-RASTREIO
ACCESS MODE IS RANDOM
FILE STATUS IS ST-ATUALIZACAO.
data division.
FILE SECTION.
FD ARQ-ATUALIZACAO.
01 REG-ATUALIZACAO.
05 ID-ATUALIZACAO PIC 9(10).
05 COD-RASTREIO PIC X(13).
05 TITULO PIC X(15).
05 DESCRICAO PIC X(30).
05 FILLER PIC X(30).
working-storage section.
01 ST-ATUALIZACAO PIC XX.
88 end-of-input-file VALUE "10".
88 INPUT-FILE-OK VALUE ZERO "10".
77 PROCURA PIC X(13).
77 RESP PIC X VALUE SPACE.
procedure division.
INICIO.
PERFORM WITH TEST AFTER UNTIL RESP = "N"
DISPLAY "CODIGO DA ENCOMENDA.:" AT 1010 ERASE SCREEN
DISPLAY "STATUS:" AT 2433
DISPLAY ST-ATUALIZACAO AT 2440
ACCEPT PROCURA AT 1030 WITH REQUIRED FULL
OPEN I-O ARQ-ATUALIZACAO
PERFORM priming-READ-input-file
PERFORM
UNTIL end-of-input-file
PERFORM process-input
PERFORM READ-input-file
END-PERFORM
DISPLAY "DESEJA CONSULTAR OUTRA ATUALIZACAO? (S/N)"
AT 2001
ACCEPT RESP AT 2044 WITH UPPER
END-PERFORM
CLOSE ARQ-ATUALIZACAO
EXIT PROGRAM
.
priming-READ-input-file.
PERFORM READ-input-file
IF end-of-input-file
DISPLAY "END OF FILE" AT 2510
END-IF
.
READ-input-file.
READ ARQ-ATUALIZACAO
IF NOT INPUT-FILE-OK
DISPLAY "FILE NOT OK" AT 2310
DISPLAY ST-ATUALIZACAO AT 2440
STOP " "
END-IF
.
process-input.
IF COD-RASTREIO = PROCURA
DISPLAY ID-ATUALIZACAO AT 2410
STOP " "
END-IF
.
我在文件 'atualizacao.dat' 中的示例数据是:
ID-ATUALIZACAO: 0000000001
COD-RASTREIO: qweqweqweqweqwee
标题:测试
DESCRICAO: 描述
ID-ATUALIZACAO: 0000000002
COD-RASTREIO: qweqweqweqweqwee
标题:test2
DESCRICAO: 描述2
因为您的 SELECT 中有 ACCESS RANDOM
,READ file-name
(没有 NEXT 或 KEY)的默认操作是键读。
将其更改为 ACCESS SEQUENTIAL
无论如何将其更改为 READ file-name NEXT
,这是一个明确的顺序读取。
我总是在 READ 上使用明确的 NEXT 或 KEY,以免依赖默认行为,这取决于文件类型(和 OPEN 类型)。
我忘记说清楚的时候是我不小心复制了别人的例子,对不起我错过了你原来没有NEXT。
因为您没有使用 OPEN I-O(您没有进行键控读取或启动,所以您不需要 RANDOM 或 DYNAMIC 来访问)只需使用 OPEN ... INPUT
.
您没有提到用户输入的要求。 perhaps/probably 用户输入不需要循环。
您没有在打开后检查文件状态字段。你会发现你在那里有问题。在同一个程序中多次打开同一个文件是不好的做法,即使你多次关闭文件(你没有这样做,所以可能会有问题。
好的,首先阅读。好的,先回到 SELECT.
上的文件状态
在一个文件上使用 FILE STATUS 可以得到一个两字节的字段,它告诉您上次 IO 操作发生了什么。如果该字段包含零,则一切都很好。
我建议对您可能使用的所有文件使用文件状态,并在文件上的每个 IO 之后检查文件状态字段(使每个文件保持唯一)。
使用文件的文件状态告诉 COBOL 运行-time "I'm going to deal with any problems that arise, you tell me when there was a problem by putting a code in this field".
如果您使用文件状态并且不检查文件状态字段,IO 错误会悄悄消失。
现在回到阅读。
这将读取下一条可用记录。
READ file-name
如果遇到文件结尾,文件状态字段将设置为“10”。
您可以为文件状态字段定义 88 级条件名称:
01 input-file-status PIC XX.
88 end-of-input-file VALUE "10".
你的循环可以是:
PERFORM
UNTIL end-of-input-file
READ input-file
END-PERFORM
仅仅读取文件没有多大用处,您还想处理数据。使代码更复杂的一种方法是在 READ 和 PERFORM 之后测试输入文件结尾,如果不是:
PERFORM
UNTIL end-of-input-file
READ input-file
IF NOT end-of-input-file
PERFORM process-input
END-IF
END-PERFORM
将其与 "priming read" 进行比较,这意味着您在开始循环之前读取了第一条记录(如果存在):
READ input-file
PERFORM
UNTIL end-of-input-file
PERFORM process-input
READ input-file
END-PERFORM
每次执行 PERFORM 时,要么有一个记录可供处理,要么在上一个 PERFORM 的末尾标识了文件末尾。
将它与您拥有的东西进行比较:
PERFORM
UNTIL ARE-THERE-MORE-RECORDS = 'NO '
READ ARQ-ATUALIZACAO
AT END
MOVE 'NO ' TO ARE-THERE-MORE-RECORDS
NOT AT END
PERFORM 300-STORE-NAME
END-READ
END-PERFORM
我说过在每次 IO 后测试文件状态字段。那会让事情看起来很乱,那么如何避免呢?执行:
PERFORM READ-input-file
PERFORM
UNTIL end-of-input-file
PERFORM process-input
PERFORM READ-input-file
END-PERFORM
然后 READ-input-file 可以检查文件状态字段(88 级)而不会使代码混乱。
进一步改进。你有两个 "read" 的 PERFORM,但它们不一样,所以给它们取不同的名字:
PERFORM priming-READ-input-file
PERFORM
UNTIL end-of-input-file
PERFORM process-input
PERFORM READ-input-file
END-PERFORM
然后:
priming-READ-input-file.
PERFORM READ-input-file
.
现在的代码和以前一样,但讲述了一个更好的故事。并且可以进一步改进,而不复杂化:
priming-READ-input-file.
PERFORM READ-input-file
IF end-of-input-file
do something which says "hey, there should always be records,
a bad thing has happened" and then crash whilst DISPLAYing
necessary information
END-IF
.
然后你就有了一个通用的、简单的程序,它循环读取文件直到文件结束,你可以在任何需要的时候将其用作基础。
您可以轻松地沿着相同的行扩展代码以处理文件上的 "file header",然后进行一些更改以处理 "file trailer",确保每个只有一个,头在前,尾在后,头用于正确的文件和正确的业务日期,尾有正确的记录数和哈希总数。
一切都不会干扰程序的控制逻辑。
然后你有第二个程序,你也可以用作基础。
对于您的任务,您首先需要与用户交互、存储用户数据、针对每条记录测试数据。这可能是一条用户输入,也可能是几条,你没说。
如果用户的输入取决于已经显示的结果,您只需要存储文件中的记录。可能是这样,你没说。
如果用户提供一个输入来匹配一个字段,则在处理每条记录时只需测试该值(已获取)。
你原来的程序有问题:
FILE STATUS 在 SELECT 上使用但未检查文件状态字段 (ST-ATUALIZACAO)。
文件的第二次打开,在 300-STORE-NAME 中将失败(文件已经打开)。
关闭 300-STORE-NAME 中的文件。哪个会起作用。但是现在,当您执行下一次 READ 时,您的文件已关闭。所以 READ 将不起作用。它怎么会不起作用(确切地说它会做什么)?好吧,我认为,因为我不知道,因为我不那样编码 , 对指定文件状态的已关闭文件的 READ 和 AT END 将导致 AT END 被处理。 FD下01级的内容肯定是undefined
每次向 table 添加记录时,您都在尝试搜索 table。如果您 需要 将所有记录存储在 table 中,只有在到达文件末尾并且所有内容都在 [=138= 中时才进行搜索].
一旦你有一个工作程序,还有另一个 StackExchange 站点,称为 Code Review,你可以在那里询问如何使工作代码更好。
制作一个非常简单的程序,循环读取输入文件,直到文件结束。
在该程序开始时,获取用户输入。如果有多个用户输入,将其存储在 table 中,并带有 OCCURS。
对于读取的每条记录,检查用户数据(单个字段,或 table)并在匹配时生成输出。
在这里查看答案,Cobol Read statement format. Can it be redone a different way?,然后关注 link。注意如何使用启动读取,以及如何使用文件状态字段实际检查错误并在顺序读取文件时识别文件结尾。
我是 COBOL 新手,在 .dat 文件中搜索特定条目时遇到问题。 这个想法是在文件中搜索在其中一个字段中具有特定代码的所有记录。
我试图在 google 中找到答案,但无论我走到哪里,答案都是不同的,我不知道为什么我不能使它们适应我的问题。
我也发现了这个问题:
How to insert records in a table in a text file using COBOL and search and display record(s) which satisfy a condition?
但答案不详
这是我的代码:
IDENTIFICATION DIVISION.
program-id. AR AS "A.AR".
environment division.
configuration section.
special-names. DECIMAL-POINT IS COMMA.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT ARQ-ATUALIZACAO ASSIGN "C:\temp\atualizacao.dat"
ORGANIZATION IS INDEXED
ACCESS MODE IS SEQUENTIAL
RECORD KEY IS ID-ATUALIZACAO
ALTERNATE RECORD KEY IS COD-RASTREIO
FILE STATUS IS ST-ATUALIZACAO.
data division.
FILE SECTION.
FD ARQ-ATUALIZACAO.
01 REG-ATUALIZACAO.
05 ID-ATUALIZACAO PIC 9(10).
05 COD-RASTREIO PIC X(13).
05 TITULO PIC X(15).
05 DESCRICAO PIC X(30).
05 FILLER PIC X(30).
working-storage section.
01 WS-RECORD.
03 ENTRIES OCCURS 18 TIMES INDEXED BY I.
05 WS-ID PIC 9(10).
05 WS-RAST PIC X(13).
05 WS-TIT PIC X(15).
05 WS-DESC PIC X(30).
77 ARE-THERE-MORE-RECORDS PIC XXX VALUE "YES".
77 NAME-COUNT PIC 99.
77 PROCURA PIC X(13).
77 ST-ATUALIZACAO PIC XX VALUE SPACES.
procedure division.
OPEN INPUT ARQ-ATUALIZACAO
PERFORM UNTIL ARE-THERE-MORE-RECORDS = 'NO '
READ ARQ-ATUALIZACAO
AT END
MOVE 'NO ' TO ARE-THERE-MORE-RECORDS
NOT AT END
PERFORM 300-STORE-NAME
END-READ
END-PERFORM
CLOSE ARQ-ATUALIZACAO.
300-STORE-NAME.
ADD 1 TO NAME-COUNT
MOVE REG-ATUALIZACAO TO ENTRIES OF WS-RECORD(NAME-COUNT).
OPEN I-O ARQ-ATUALIZACAO
DISPLAY "CODIGO DA ENCOMENDA.:" AT 1010
DISPLAY "STATUS:" AT 2433
DISPLAY ST-ATUALIZACAO AT 2440
ACCEPT PROCURA AT 1030 WITH REQUIRED FULL
SEARCH ENTRIES
AT END DISPLAY "CODIGO NAO ENCONTRADO" AT 0210
WHEN WS-RAST(I) = PROCURA
DISPLAY "REGISTROS ENCONTRADOS" AT 0210
DISPLAY WS-RAST(I) AT 0310
DISPLAY WS-ID(I) AT 0410
DISPLAY WS-TIT(I) AT 0510
DISPLAY WS-DESC(I) AT 0610
END-SEARCH
CLOSE ARQ-ATUALIZACAO
EXIT PROGRAM.
编辑 - 我更改了很多代码,所以我将 post 新代码放在这里:
IDENTIFICATION DIVISION.
program-id. ATUALIZACAOR AS "ATUALIZACAO.ATUALIZACAOR".
environment division.
configuration section.
special-names. DECIMAL-POINT IS COMMA.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT ARQ-ATUALIZACAO ASSIGN "C:\temp\atualizacao.dat"
ORGANIZATION IS INDEXED
RECORD KEY IS ID-ATUALIZACAO
ALTERNATE RECORD KEY IS COD-RASTREIO
ACCESS MODE IS RANDOM
FILE STATUS IS ST-ATUALIZACAO.
data division.
FILE SECTION.
FD ARQ-ATUALIZACAO.
01 REG-ATUALIZACAO.
05 ID-ATUALIZACAO PIC 9(10).
05 COD-RASTREIO PIC X(13).
05 TITULO PIC X(15).
05 DESCRICAO PIC X(30).
05 FILLER PIC X(30).
working-storage section.
01 ST-ATUALIZACAO PIC XX.
88 end-of-input-file VALUE "10".
88 INPUT-FILE-OK VALUE ZERO "10".
77 PROCURA PIC X(13).
77 RESP PIC X VALUE SPACE.
procedure division.
INICIO.
PERFORM WITH TEST AFTER UNTIL RESP = "N"
DISPLAY "CODIGO DA ENCOMENDA.:" AT 1010 ERASE SCREEN
DISPLAY "STATUS:" AT 2433
DISPLAY ST-ATUALIZACAO AT 2440
ACCEPT PROCURA AT 1030 WITH REQUIRED FULL
OPEN I-O ARQ-ATUALIZACAO
PERFORM priming-READ-input-file
PERFORM
UNTIL end-of-input-file
PERFORM process-input
PERFORM READ-input-file
END-PERFORM
DISPLAY "DESEJA CONSULTAR OUTRA ATUALIZACAO? (S/N)"
AT 2001
ACCEPT RESP AT 2044 WITH UPPER
END-PERFORM
CLOSE ARQ-ATUALIZACAO
EXIT PROGRAM
.
priming-READ-input-file.
PERFORM READ-input-file
IF end-of-input-file
DISPLAY "END OF FILE" AT 2510
END-IF
.
READ-input-file.
READ ARQ-ATUALIZACAO
IF NOT INPUT-FILE-OK
DISPLAY "FILE NOT OK" AT 2310
DISPLAY ST-ATUALIZACAO AT 2440
STOP " "
END-IF
.
process-input.
IF COD-RASTREIO = PROCURA
DISPLAY ID-ATUALIZACAO AT 2410
STOP " "
END-IF
.
我在文件 'atualizacao.dat' 中的示例数据是:
ID-ATUALIZACAO: 0000000001
COD-RASTREIO: qweqweqweqweqwee
标题:测试
DESCRICAO: 描述
ID-ATUALIZACAO: 0000000002
COD-RASTREIO: qweqweqweqweqwee
标题:test2
DESCRICAO: 描述2
因为您的 SELECT 中有 ACCESS RANDOM
,READ file-name
(没有 NEXT 或 KEY)的默认操作是键读。
将其更改为 ACCESS SEQUENTIAL
无论如何将其更改为 READ file-name NEXT
,这是一个明确的顺序读取。
我总是在 READ 上使用明确的 NEXT 或 KEY,以免依赖默认行为,这取决于文件类型(和 OPEN 类型)。
我忘记说清楚的时候是我不小心复制了别人的例子,对不起我错过了你原来没有NEXT。
因为您没有使用 OPEN I-O(您没有进行键控读取或启动,所以您不需要 RANDOM 或 DYNAMIC 来访问)只需使用 OPEN ... INPUT
.
您没有提到用户输入的要求。 perhaps/probably 用户输入不需要循环。
您没有在打开后检查文件状态字段。你会发现你在那里有问题。在同一个程序中多次打开同一个文件是不好的做法,即使你多次关闭文件(你没有这样做,所以可能会有问题。
好的,首先阅读。好的,先回到 SELECT.
上的文件状态在一个文件上使用 FILE STATUS 可以得到一个两字节的字段,它告诉您上次 IO 操作发生了什么。如果该字段包含零,则一切都很好。
我建议对您可能使用的所有文件使用文件状态,并在文件上的每个 IO 之后检查文件状态字段(使每个文件保持唯一)。
使用文件的文件状态告诉 COBOL 运行-time "I'm going to deal with any problems that arise, you tell me when there was a problem by putting a code in this field".
如果您使用文件状态并且不检查文件状态字段,IO 错误会悄悄消失。
现在回到阅读。
这将读取下一条可用记录。
READ file-name
如果遇到文件结尾,文件状态字段将设置为“10”。
您可以为文件状态字段定义 88 级条件名称:
01 input-file-status PIC XX.
88 end-of-input-file VALUE "10".
你的循环可以是:
PERFORM
UNTIL end-of-input-file
READ input-file
END-PERFORM
仅仅读取文件没有多大用处,您还想处理数据。使代码更复杂的一种方法是在 READ 和 PERFORM 之后测试输入文件结尾,如果不是:
PERFORM
UNTIL end-of-input-file
READ input-file
IF NOT end-of-input-file
PERFORM process-input
END-IF
END-PERFORM
将其与 "priming read" 进行比较,这意味着您在开始循环之前读取了第一条记录(如果存在):
READ input-file
PERFORM
UNTIL end-of-input-file
PERFORM process-input
READ input-file
END-PERFORM
每次执行 PERFORM 时,要么有一个记录可供处理,要么在上一个 PERFORM 的末尾标识了文件末尾。
将它与您拥有的东西进行比较:
PERFORM
UNTIL ARE-THERE-MORE-RECORDS = 'NO '
READ ARQ-ATUALIZACAO
AT END
MOVE 'NO ' TO ARE-THERE-MORE-RECORDS
NOT AT END
PERFORM 300-STORE-NAME
END-READ
END-PERFORM
我说过在每次 IO 后测试文件状态字段。那会让事情看起来很乱,那么如何避免呢?执行:
PERFORM READ-input-file
PERFORM
UNTIL end-of-input-file
PERFORM process-input
PERFORM READ-input-file
END-PERFORM
然后 READ-input-file 可以检查文件状态字段(88 级)而不会使代码混乱。
进一步改进。你有两个 "read" 的 PERFORM,但它们不一样,所以给它们取不同的名字:
PERFORM priming-READ-input-file
PERFORM
UNTIL end-of-input-file
PERFORM process-input
PERFORM READ-input-file
END-PERFORM
然后:
priming-READ-input-file.
PERFORM READ-input-file
.
现在的代码和以前一样,但讲述了一个更好的故事。并且可以进一步改进,而不复杂化:
priming-READ-input-file.
PERFORM READ-input-file
IF end-of-input-file
do something which says "hey, there should always be records,
a bad thing has happened" and then crash whilst DISPLAYing
necessary information
END-IF
.
然后你就有了一个通用的、简单的程序,它循环读取文件直到文件结束,你可以在任何需要的时候将其用作基础。
您可以轻松地沿着相同的行扩展代码以处理文件上的 "file header",然后进行一些更改以处理 "file trailer",确保每个只有一个,头在前,尾在后,头用于正确的文件和正确的业务日期,尾有正确的记录数和哈希总数。
一切都不会干扰程序的控制逻辑。
然后你有第二个程序,你也可以用作基础。
对于您的任务,您首先需要与用户交互、存储用户数据、针对每条记录测试数据。这可能是一条用户输入,也可能是几条,你没说。
如果用户的输入取决于已经显示的结果,您只需要存储文件中的记录。可能是这样,你没说。
如果用户提供一个输入来匹配一个字段,则在处理每条记录时只需测试该值(已获取)。
你原来的程序有问题:
FILE STATUS 在 SELECT 上使用但未检查文件状态字段 (ST-ATUALIZACAO)。
文件的第二次打开,在 300-STORE-NAME 中将失败(文件已经打开)。
关闭 300-STORE-NAME 中的文件。哪个会起作用。但是现在,当您执行下一次 READ 时,您的文件已关闭。所以 READ 将不起作用。它怎么会不起作用(确切地说它会做什么)?好吧,我认为,因为我不知道,因为我不那样编码 , 对指定文件状态的已关闭文件的 READ 和 AT END 将导致 AT END 被处理。 FD下01级的内容肯定是undefined
每次向 table 添加记录时,您都在尝试搜索 table。如果您 需要 将所有记录存储在 table 中,只有在到达文件末尾并且所有内容都在 [=138= 中时才进行搜索].
一旦你有一个工作程序,还有另一个 StackExchange 站点,称为 Code Review,你可以在那里询问如何使工作代码更好。
制作一个非常简单的程序,循环读取输入文件,直到文件结束。
在该程序开始时,获取用户输入。如果有多个用户输入,将其存储在 table 中,并带有 OCCURS。
对于读取的每条记录,检查用户数据(单个字段,或 table)并在匹配时生成输出。
在这里查看答案,Cobol Read statement format. Can it be redone a different way?,然后关注 link。注意如何使用启动读取,以及如何使用文件状态字段实际检查错误并在顺序读取文件时识别文件结尾。