【问题标题】:COBOL reading sequential line file, count charactersCOBOL读取顺序行文件,计数字符
【发布时间】:2016-07-19 07:28:17
【问题描述】:

在 COBOL 中,我正在读取顺序行文件。逐行,到EOF,类似的东西

           read bank-file  at end
            move 'Y'  to end-of-bank

行的长度从 40 到 80 个字符不等。我需要知道,每行有多少个字符。但是行可以以一些空格结尾,我也需要计算。所以我不能从程序中的变量中获取字符串的长度。 READ 语句是否有任何返回值,它从读取的行返回字符数(直到达到 CRLF)?

【问题讨论】:

  • 您尝试过吗:根据 ws-Length 语法记录从 1 到 80 的变化。不确定它是否适用于 line-sequential
  • VB QSAM 文件在每条记录的前 2 个字节中包含一个 16 位整数,它给出了记录的长度
  • @GilbertLeBlanc 是的,但我不认为这是一个 VB QSAM,因为引用了 CRLF。
  • 需要查看您的 SELECT、FD 和它的 01(s),关于哪个 COBOL 编译器和操作系统的信息。

标签: cobol


【解决方案1】:

编辑

正如 cmets 中提到的,实际上可以获取读取的字符(字节)数,确实可以使用RECORD VARYING DEPENDING ON 子句:

ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.

    SELECT SOME-FILE
        ASSIGN TO "someFile.txt"
        ORGANIZATION IS LINE SEQUENTIAL.

DATA DIVISION.
FILE SECTION.

FD SOME-FILE
    RECORD VARYING 40 TO 80 DEPENDING ON SOME-LINE-LENGTH.

 01 SOME-LINE PIC X(80).

WORKING-STORAGE SECTION.

 77 SOME-LINE-LENGTH PIC 9(3).

现在对于每次读取,记录长度存储到SOME-LINE-LENGTH

READ SOME-FILE NEXT RECORD
DISPLAY SOME-LINE-LENGTH

我不确切知道哪些供应商支持它(可能几乎所有),但至少它适用于 ACUCOBOL。


原帖

据我所知,执行READ语句读取的字节数没有反馈。显然,字节会立即存储到您的FILE SECTION 中的文件描述符所描述的记录中。

但是,您可以通过计算写入记录的字符数来计算读取的字节数。
首先,将文件记录初始化为LOW-VALUES。然后读取下一条记录;这会将读取的字节数移动到记录中。当读取的字节数小于记录大小时,记录末尾的字节保持不变。

MOVE LOW-VALUES TO YOUR-RECORD
READ YOUR-FILE NEXT RECORD
PERFORM VARYING SOME-COUNTER FROM 72 BY -1 UNTIL (SOME-COUNTER < 0)
    IF NOT (YOUR-RECORD(SOME-COUNTER : 1) = LOW-VALUES)
        EXIT PERFORM
    END-IF
END-PERFORM

SOME-COUNTER 将包含行长,假设文件中没有 NUL 值。

我想当行数很大时这会很耗时,但至少你有你的行长。


正如Bill Woodger 已经提到的,由于您没有提供额外的细节,我不得不做出一些假设。

我自己在 Windows 10 上运行 MicroFocus ACUCOBOL-GT。

【讨论】:

  • 最好包含编译器名称,因为这取决于实现。它可能适用于大多数 COBOL 编译器,但不是全部。如果您看到 Gilbert 对该问题的评论,您可以尝试一些方法。记录取决于...
  • @MCEmperor,正如 cmets 在这里多次提到的,您应该查看FD infile RECORD VARYING DEPENDING ON infile-record-length.,它可能会为您的 ACUCOBOL 程序节省一点计算时间。并且注意NULL,它与LOW-VALUEx"00"不一样,NULL是指指针的内容,而不是零字节。
  • @MCEmperor 当然,但这是一个非标准的实现细节。例如,该代码将在 GnuCOBOL 上大放异彩。话虽如此,我非常喜欢在编译器处理代码时脱离规范,但它不能移植到其他供应商的 COBOL。 ACUCOBOL-GT 有一些不错的扩展,所以不妨利用一下。
  • @BrianTiffin 是的。问题是我不确切知道其他编译器如何处理事情。但是,是的,我猜 X'00' 会做(只要他们有一个“正常”的字符集)。
【解决方案2】:

如果你仍然不知道你有多少字节,试试这个:

关于 cobol 在 unix/linux/pcs 上的奇妙之处在于,在大多数情况下,他们不检查文件结构,他们认为你足够聪明,可以告诉程序文件是什么,并且在复杂文件的情况下,例如一个嵌入在文件中的 MFCobol B-Tree 索引,文件头将完成剩下的工作。

我第一次接触 MFCobol 时,用户总是收到损坏的文件,我们需要一种方法来快速知道出了什么问题,所以我利用这一事实,基本上解析文件以寻找某些特征,例如 x' 0A' (UNIX) 或 CR/LF,它会告诉我们有人使用二进制传输将文件从 PC FTP 到 LINUX。它完全符合我们的预期,最终我们将其作为最终用户实用程序发布。

基于此,您可以只告诉文件它有 1 个字节的记录,并将每个字节作为二进制顺序读取。这可以让您在经过时计算字节数。将文件定义更改为 BINARY SEQUENTIAL,记录大小为 pic x(01)。由于您声明记录终止符是 CR/LF,因此您需要一个 2 字节字段来进行模式识别,并减少分隔符的字节数。

SELECT SOME-FILE
    ASSIGN TO "someFile.txt"
    ORGANIZATION IS BINARY SEQUENTIAL.

 DATA DIVISION.
 FILE SECTION.

 FD SOME-FILE
    01 SOME-BYTE PIC X(01).

 WORKING-STORAGE SECTION.
 01 PATTERN-BUFFER.
    05  PB-01  PIC X(01).
    05  PB-02  PIC X(01).
 01  BYTE-COUNT      PIC 9(9) VALUE ZERO.
 01  END-OF-SOME-FILE   PIC X(01) VALUE IS "N"

PROCEDURE DIVISION.
MAIN.
  open SOME-FILE.
  READ SOME-FILE INTO SOME-BYTE
  AT END
     CLOSE SOME-FILE
     DISPLAY  "BYTE-COUNT: 0"
     STOP RUN
  NOT AT END
      MOVE 1 TO BYTE-COUNT
      PERFORM UNTIL END-OF-SOME-FILE="Y"
         READ SOME-FILE       **  (1 byte record)
           AT END MOVE "Y" TO END-OF-SOME-FILE
              DISPLAY BYTE-COUNT
              STOP RUN
           NOT AT END
              ADD 1 to BYTE-COUNT
              MOVE PB-02 to PB-01 
              MOVE SOME-BYTE TO PB-02
              IF PATTERN-BUFFER = x'0D0A'
                 SUBTRACT 2 FROM BYTE-COUNT
              ELSE
                 IF PB-01 = x'00" AND PB-02 < X'20'   <<=== SEE NOTE
                    SUBTRACT 1 FROM BYTE=COUNT
                 END-IF
              END-IF
         END-READ
     END-PERFORM
END-READ

MF COBOL 可以选择对 LINE SEQUENTIAL 文件执行两件事,这可能会影响您的计数。

首先是删除所有尾随空格...但根据规范,您想要实际存储的字节数应该没问题。

第二个是标记在某些情况下可能被误解的字符。对于可能看起来像二进制整数值的回车控制字符尤其如此。如果 MF Cobol 看到一个小于空格的 ascii 值的值,它将在其前面的标志字节中放置一个二进制 0 值。这个标志字节在文件中占用空间时不是数据,它是文件结构标记和通常不会在您的输出计数中找到自己,但是因为我们使文件二进制顺序,它不会在运行时从读取中删除,因此如果您看到一个 LOW-VALUE 或 x'00' 后跟一个字符小于 x'20 的值”然后将输出字节数减少 1。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多