您定义了两个记录,您可以完全按照您所显示的那样,在一个 FD 下进行。这会给你一个隐含的 REDEFINES。
在文件的 SELECT 语句中使用 FILE STATUS(总是)。始终检查文件状态字段是否获得预期值。使用 88 条件名称作为“10”值来标识文件结尾。不要使用AT END/NOT AT END。
请注意,您的练习不能完美地完成此操作,因为该文件尚未正确定义。没有可用于标识标题记录或数据记录的指示。唯一的指示是“头在前,其余都是数据”。这可能看起来不错,但是当有人腌制最初编写文件的程序时就会变得懒惰,并且没有给你任何标题,或者两个或更多标题。
如果文件具有结构,则该结构应该在数据中,因为它可以被检查。像处理好文件一样处理坏文件可能会非常昂贵。而且很尴尬。
您还需要知道文件是否允许为“空”。由于它有一个标题记录,一个“空”文件应该包含一个数据记录计数为零的标题记录。您的情况可能会有所不同,因为该文件不是经过设计的。
在您的初始处理中(在您的输入文件为OPENed 之后),您读取了第一条记录。如果是这样,请处理“空文件”。检查它是一个标题。存储记录数。
然后您阅读下一条记录。你检查它是 not 一个标题。
然后你处理你的数据,记住你有第一个可用的数据记录。
Loop until end-of-input
process record
read next record
End-Loop
在文件末尾(循环结束时),您检查标题上的记录数(从存储的值)到您读取的数据记录数(在记录处理中计算)。
一旦你有了你的程序,你就有了一个“模型”来作为其他程序的基础。您只需将“这就是我处理文件的方式”正确一次,然后将其用作下一个文件处理程序的起点。下一个程序会更复杂,所以你最终会得到另一个模型。
一段时间后,您将拥有大约五个模型,每个模型都基于来自更简单任务的工作代码。
我反对使用AT END/NOT AT END 读取文件有几个原因:
复杂性和可理解性
a-pargraph-for-SO-formatting.
PERFORM priming-read
PERFORM
UNTIL end-of-infile
PERFORM process-data
PEFORM read-next
END-PERFORM
.
priming-read.
PERFORM read-next
.
read-next.
READ IN-FILE
IF NOT IN-FILE-STATUS-OK
PERFORM diagnostic-message-and-fail
END-IF
.
对比
PERFORM UNTIL WS-EOF='Y'
READ STUDENT INTO WS-STUDENT
AT END MOVE 'Y' TO WS-EOF
NOT AT END DISPLAY WS-STUDENT
END-READ
END-PERFORM
您不能在未测试 WS-EOF 的情况下在 END-READ 之后放置任何代码。然而人们会这样做。
可靠性和操作简便性
如果在 SELECT 中为文件指定了 FILE STATUS,则由程序员对其进行测试。如果出现问题,显然 AT END 不正确,但没有新记录。随后的 READ 将得到相同的情况,并且随之而来的是 Big Fat Loop。所以应该测试文件状态字段(如果使用文件状态),那么为什么不使用文件状态字段来测试文件结束,因为它更简单,而不是进一步的条件没有结束。
当然,如果你不使用 FILE STATUS,运行时会处理一些事情,但是以一种广泛而直接的方式,没有机会提供额外的诊断信息,
当然,您也可以使用 USE AFTER... 但这会更加复杂,因为有些东西很多人不习惯。
它鼓励使用 GO TO 来“摆脱困境”
READ IN-FILE
AT END GO TO no-more-records
END-READ
为什么要在FD下定义记录,为什么不在WORKING-STORAGE中
或者,READ ... 和 READ ... INTO ... 有什么区别?
FILE SECTION 中的FD 允许描述“记录区”中的记录。
对于输入文件,这将是成功读取的最后一条记录。如果有的话。文件的打开将使记录区域可用。一旦遇到文件结尾,将不再有当前记录。文件关闭时也不会有当前记录(无论是否到达文件结尾)。
这意味着您不应该在文件打开之前、关闭之后或到达文件结尾之后访问记录区域。在 IBM 大型机上不应该经常不能,因为它很容易导致S0C4 异常结束,即保护异常。输入区域实际上是在处理文件的 IO 例程中定义的,而不是在您的 COBOL 程序中。 FD 只是将您的定义映射到记录区域的地址。如果当时记录区不存在,则无法访问。
对于一个简单的文件结构,您不需要同时访问来自不同记录的数据,您始终可以使用 FD。
对于更复杂的结构,您需要存储来自不同记录类型的数据,因为FD下只有当前记录可用。
您可以存储整个记录,也可以只存储您需要的部分。
您可以在 READ 之后的某个时间点使用 MOVE 为各个字段存储您需要的部分。
您可以在 READ 之后通过 FD 下的整个记录的 MOVE 存储整个记录,或者使用 READ ... INTO ... 自动执行此操作。
READ ... INTO ... 对输入文件中的每条记录执行 MOVE(隐式)。如果您不需要它,那就是浪费资源,而且由于人们为大型机上的资源(如使用的 CPU)付费,因此除非您迫切需要,否则值得避免。
网站通常有当地标准。你遵循标准,即使它们不好(你试图改变它们,并不总是成功)。如果你被告知使用 READ ... INTO ... 你就使用它。
但是,作为参考,我不使用 READ ... INTO ...(除非在上述情况下),并且在使用 FD 和移动我想要的数据(单个字段或整个记录)。
使用 FD 是“最好的”。除非当地标准另有规定。那么按照当地的标准是“最好的”。
请注意,有些东西会修改上述内容并为您的程序中的记录创建特定区域。如果 INTO(以及 WRITE 上的 FROM)可以让您的整个记录被隐式移动两次。