如何处理具有两种不同类型记录的顺序文件? [英] How do I process a sequential file with two different types of records?

查看:56
本文介绍了如何处理具有两种不同类型记录的顺序文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于作为COBOL课程一部分的作业,我的输入文件是一个名为BRANCHTOT.SEQ的顺序文件,具有两种记录类型:



第一个是我调用标头记录,该标头记录指出文件中的记录总数(标头记录本身除外)。这只是一个记录。



如果这是文件中唯一的记录,我将其定义如下:

  01头记录。 
03记录计数PIC 9(6)。
03 FILLER PIC X(13)。

第二种类型的记录是我将要读取并处理输出的记录。其结构如下:

  01销售记录。 
03 branch-nr PIC X(5)。
03 office-nr PIC 9(2)。
03计算PIC 9(5)。
03总和PIC 9(5)V99。




  1. 如何在文件部分中定义BRANCHTOT.SEQ文件并工作存储部分?我使用重新定义吗?

我习惯于处理具有一种记录类型的文件。


  1. 如何在不妨碍标题记录的情况下读取和处理记录的销售记录类型?

赋值比我在这里描述的要复杂得多,但是
是我程序中存在的部分问题读取和处理销售记录记录,并打印已读取的所有记录的总数量,并将其与抬头记录中列出的数量进行比较。如果两者不匹配,则需要在输出列表中声明一条错误消息。


  1. 我该如何处理?


解决方案

您定义了两条记录,都可以在单个 FD 。



在文件的SELECT语句上始终使用FILE STATUS(文件状态)。始终检查文件状态字段是否获得期望值。使用88条件名称作为值 10来标识文件结尾。不要使用 AT END / NOT AT END



请注意,由于文件定义不正确,您无法完美地进行此操作。没有可用于标识标头记录或数据记录的指示。唯一的指示是头是头,其余的都是数据。听起来似乎不错,但是当有人通过腌制程序最初编写文件时,却没有任何标题,或者没有两个或多个标题时,就会变得无聊。



文件具有结构,该结构应在数据之内,因为可以对其进行检查。像处理好文件一样处理坏文件可能会非常昂贵。和尴尬。



还需要知道文件是否为空。由于它具有头记录,因此空文件应由数据记录计数为零的头记录组成。



在您的初始处理过程中(输入文件 OPEN

c> ed),您将读取第一条记录。如果是这样,请处理空文件。检查它是否为标题。存储记录数。



然后读取下一条记录。您检查它是不是不是标头。



然后处理数据,记住您拥有第一条可用数据记录。

 直到输入结束
过程记录为止的循环
读取下一条记录
结束循环

在文件结束时(循环结束时),您检查标头上的记录数(从存储的值)到读取的数据记录数(已计数)



一旦有了您的程序,便有了一个模型来作为其他程序的基础。您只需一次正确地获得常规的这就是我处理文件的方式,然后将其用作下一个文件处理程序的起点。下一个程序将更加复杂,因此您将获得另一个模型。



以后,您将拥有大约五个模型,每个模型都基于一个简单任务的工作代码。



我反对使用 AT END / NOT AT END 读取文件的原因有几个:



复杂性和可理解性

  a- SO格式的段落。 
执行预读-
执行
直到文件结尾
执行过程数据
PEFORM读取下一个
结束执行

启动读。
执行,下一个

接下来读取。
读取文件
,如果未进入文件中状态
执行诊断消息并失败
结束,如果

Vs。

 执行直到WS-EOF ='Y'
将学生读入WS-学生
最终将'Y'移至WS-EOF
不在屏幕上显示WS-STUDENT
END-READ
END-PERFORM

您不能在后面加上任何代码END-READ,无需测试WS-EOF。



可靠性和易操作性



如果文件状态为在SELECT中为文件指定大小,然后由程序员进行测试。如果出了什么问题,显然在END END是不正确的,但是没有新的记录。随后的读取将得到相同的情况,然后出现大胖循环。因此,应该测试file-status-field(如果使用了FILE STATUS),那么,为什么不使用file-status-field来测试文件结尾,因为它比较简单,而不是在文件中的其他条件。



当然,如果您不使用FILE STATUS,则运行时将处理所有事情,但是方式会很粗鲁,没有提供其他诊断信息的机会,



当然,您也可以使用USE ...之后,但这会使情况更加复杂,其中有许多未使用



它鼓励使用GO TO摆脱困境

 最后读入文件
转到不再有记录
END-READ

为什么在FD下定义记录,为什么不在WORKING-STORAGE中



或者, READ ... READ ... INTO ... 有什么区别?



文件部分 FD c>允许在记录区域中记录的描述。



对于输入文件,这将是成功读取的最后一条记录。如果有一个。打开文件将使记录区域可用。一旦遇到文件结束,将不再有当前记录。关闭文件(无论是否达到文件结尾)时,都不会有当前记录。



这意味着您不应访问以下记录:文件打开之前,文件关闭之后或到达文件结尾之后的区域。在IBM大型机上通常不应该不能,因为它很容易导致 S0C4 异常终止,这是保护异常。输入区域实际上是在处理文件的IO例程中定义的,而不是在COBOL程序中定义的。 FD只是将您的定义映射到记录区域的地址。如果记录区域当时不存在,则无法访问它。



对于简单的文件结构,您无需访问



对于同时来自不同记录的数据,您可以始终使用FD。对于更复杂的结构,您需要存储来自不同记录类型的数据,例如FD中只有当前记录可用。



您可以存储整个记录,也可以存储所需的部分。



您可以在读取后的某个时刻仅存储MOVE所需的各个字段的部分。



您可以通过MOVE来存储整个记录。读取后,或使用READ ... INTO ...会自动完成FD下的整个记录​​。



READ ... INTO ...执行移动(隐式)输入文件上的每个记录。如果您不需要它,那将浪费资源,而且由于人们在大型机上购买资源(例如使用的CPU),因此除非您非常需要它,否则值得避免。



站点通常具有本地标准。即使这些标准不好,您也要遵守这些标准(尝试更改它们,但不一定总能成功)。



但是,作为参考,我不使用READ ... INTO .. (除非在上述情况下),并且从未使用FD和移动所需的数据(单个字段或整个记录)遇到问题。



它是使用FD的最佳方法。除非当地标准另有规定。



请注意,有些事情会修改上面的内容并为程序中的记录创建特定区域。如果INTO(和FROM上的FROM)可以隐式地两次获得整个记录MOVEd。


For an assignment as part of a COBOL course, my input file is a sequential file called BRANCHTOT.SEQ with two types of records:

The first is what I call a header record that states the total amount of records in the file (excluding the header record itself). This is only one record.

If this were to be the only record in the file, I'd define it as follows:

01 header-record.
   03 record-count  PIC 9(6).
   03 FILLER        PIC X(13). 

The second type of records are the records I will have to read and process for the output. Its structure is as follows:

01 sales-record.
   03 branch-nr    PIC X(5).
   03 office-nr    PIC 9(2).
   03 count        PIC 9(5).
   03 sum          PIC 9(5)V99.

  1. How do I define the BRANCHTOT.SEQ file in my FILE SECTION and WORKING-STORAGE SECTION? Do I use a redefine?

I'm used to working with files with one type of record.

  1. How do I read and process the sales-record type of records without the header-record getting in the way?

The assignment is much more complex than I'm describing here, but for this part of the problem my program has to read and process the sales-record records and print the total amount of these records it has read, and compare that to the amount listed in the header-record. If the two don't match I need to have a statement in my output list to note this error.

  1. How do I go about this?

解决方案

You define both of your records, you can do so exactly as you have shown, under a single FD. This will give you an implicit REDEFINES.

Use FILE STATUS (always) on your SELECT statement for the file. Always check that the file-status field gets an expected value. Use an 88 condition-name for a value of "10" to identify end-of-file. Do not use AT END/NOT AT END.

Note that you can't do this perfectly for your exercise, because the file has not been defined correctly. There is no indication available to identify either a header record, or a data record. The only indication is that "the header is first, all the rest are data". That may seem fine, but turns to slok when someone pickles the program writing the file originally, and gives you no header, or two-or-more headers.

If a file has a structure, the structure should be within the data, because it can then be checked. Processing a bad file as though it were a good one can be very costly. And embarrassing.

Also you need to know whether it is permissible for the file to be "empty". Since it has a header record, an "empty" file should consist of a header record with a zero data-record count. Your case may be different, as the file is not designed.

Within your initial processing (after your input file is OPENed), you read the first record. Deal with the "empty file" if it is so. Check it is a header. Store the record-count.

You then read the next record. You check it is not a header.

Then you process your data, remembering that you have the first data-record available.

Loop until end-of-input
  process record
  read next record
End-Loop

At end-of-file (when the loop finishes) you check the number of records on the header (from the stored value) to the number of data-records you read (counted within the processing of the record).

Once you have your program, you then have a "model" to base other programs on. You only have to get the general "this is the way I process a file" correct once, and then use that as a starting-point for your next file-processing program. That next program will be more complicated, so you end up with another model.

After time you'll have about five models, each based on the working code from a simpler task.

There are several reasons I argue against the use of AT END/NOT AT END for READ of a file:

Complexity and understandability

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
   .

Vs.

  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

You can't put any code after the END-READ without testing the WS-EOF. Yet people do.

Reliability and ease of operation

If FILE STATUS is specified for a file in the SELECT then it is down to the programmer to test it. If something is wrong, AT END, clearly, is not true, yet there is no new record. A subsequent READ will get the same situation, and a Big Fat Loop ensues. So the file-status-field should be tested (if FILE STATUS is used), so, why not use the file-status-field to test for end-of-file, since it is simpler, rather than a further condition within the NOT AT END.

Of course, if you don't use FILE STATUS, the run-time will deal with things, but in a broad-and-blunt manner, with no opportunity for the supply of additional diagnostic information,

Also of course, you could use USE AFTER... but that further complicates, with something many aren't used to.

It encourages the use of GO TO to "get out of a mess"

READ IN-FILE
  AT END GO TO no-more-records
END-READ

Why define the records under the FD, why not in WORKING-STORAGE

Or, what is the difference between READ ... and READ ... INTO ...?

The FD in the FILE SECTION allows description of the record in the "record area".

For an input file, this will be the last record successfully read. If there is one. The OPEN of a file will make a record-area available. Once end-of-file is encountered, there will no longer be a current record. Neither will there be a current record when the file is CLOSEd (whether end-of-file is reached or not).

This means you shouldn't access a record-area before a file is OPENed, after it is CLOSEd, or after end-of-file is reached. On an IBM Mainframe shouldn't is often can't as it can readily cause a S0C4 abend, a Protection Exception. The input area is actually defined in the IO-routines which process the files, not in your COBOL program. The FD just maps your definitions to the address of the record-area. If the record-area doesn't exist at the time, you can't access it.

For a simple file-structure, where you don't need access to data from different records at the same time, you can always use the FD.

For a more complex structure, you need to store data from the different record-types, as only the current record is available under the FD.

You can store the entire record, or just the parts you need.

You can store just the parts you need with MOVEs for the individual fields at some point after the READ.

You can store entire records by a MOVE of the entire record under the FD after the READ, or by using READ ... INTO ... which does that automatically.

READ ... INTO ... does the MOVE (implicit) for every record on your input file. If you don't need that, it is a waste of resources, and since people pay for resources (like CPU used) on a Mainframe, it is worth avoiding unless you desperately need it.

Sites usually have local standards. You follow the standards, even if they are not good (you try to change them, don't always succeed). If you are told to use READ ... INTO ... you use it.

However, for information, I don't use READ ... INTO ... (unless in the above case) and have never encountered a problem using the FD and MOVEing the data I want (either individual fields, or an entire record).

It is "best" to use the FD. Unless the local standard dictates otherwise. Then it is "best" to follow the local standard.

Just to note, there are some things which modify the above and create a specific area for a record in your program. If INTO (and FROM on a WRITE) can get your entire record MOVEd implicitly twice.

这篇关于如何处理具有两种不同类型记录的顺序文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆