COBOL 读取顺序行文件,计算字符
COBOL reading sequential line file, count characters
在 COBOL 中,我正在从顺序行文件中读取。逐行,到 EOF,诸如此类
read bank-file at end
move 'Y' to end-of-bank
行的长度从 40 到 80 个字符不等。我需要知道每行有多少个字符。但是行可以以一些空格结尾,我也需要计算这些空格。所以我不能从程序中的变量中获取字符串的长度。 READ 语句中是否有任何 return 值,即读取行中的 returns 个字符数(直到达到 CRLF)?
编辑
如评论中所述,实际上 是 可以获取读取的字符数(字节),确实使用 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。
原版post
据我所知,执行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已经提到的,由于您没有提供额外的细节,我不得不做出一些假设。
我 运行 MicroFocus ACUCOBOL-GT 我自己 Windows 10。
以防万一你仍然不知道你有多少字节,试试这个:
unix/linux/pcs 上关于 cobol 的美妙之处在于,在大多数情况下,他们不检查文件结构,他们假设您足够聪明,可以告诉程序文件是什么,并且在文件复杂的情况下例如嵌入文件中的 MFCobol B-Tree 索引,文件头将完成其余工作。
我第一次接触 MFCobol 时,用户总是以损坏的文件告终,我们需要一种方法来快速了解问题出在哪里,所以我利用了这一事实,基本上解析了文件以寻找某些功能,例如x'0A' (UNIX) 或 CR/LF 会告诉我们有人 FTP 使用二进制传输将文件从 PC 传输到 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 看到一个值小于 space 的 ascii 值,它会在它前面的标志字节中放置一个二进制 0 值。这个标志字节在文件中取 space 时不是数据,它是一个文件结构标记,通常不会在您的输出计数中找到它自己,但是因为我们使文件二进制顺序,它不会在运行时从读取中删除,因此如果您看到 LOW-VALUE 或 x '00' 后跟一个值小于 x'20" 的字符,然后将输出字节数减少 1。
在 COBOL 中,我正在从顺序行文件中读取。逐行,到 EOF,诸如此类
read bank-file at end
move 'Y' to end-of-bank
行的长度从 40 到 80 个字符不等。我需要知道每行有多少个字符。但是行可以以一些空格结尾,我也需要计算这些空格。所以我不能从程序中的变量中获取字符串的长度。 READ 语句中是否有任何 return 值,即读取行中的 returns 个字符数(直到达到 CRLF)?
编辑
如评论中所述,实际上 是 可以获取读取的字符数(字节),确实使用 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。
原版post
据我所知,执行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已经提到的,由于您没有提供额外的细节,我不得不做出一些假设。
我 运行 MicroFocus ACUCOBOL-GT 我自己 Windows 10。
以防万一你仍然不知道你有多少字节,试试这个:
unix/linux/pcs 上关于 cobol 的美妙之处在于,在大多数情况下,他们不检查文件结构,他们假设您足够聪明,可以告诉程序文件是什么,并且在文件复杂的情况下例如嵌入文件中的 MFCobol B-Tree 索引,文件头将完成其余工作。
我第一次接触 MFCobol 时,用户总是以损坏的文件告终,我们需要一种方法来快速了解问题出在哪里,所以我利用了这一事实,基本上解析了文件以寻找某些功能,例如x'0A' (UNIX) 或 CR/LF 会告诉我们有人 FTP 使用二进制传输将文件从 PC 传输到 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 看到一个值小于 space 的 ascii 值,它会在它前面的标志字节中放置一个二进制 0 值。这个标志字节在文件中取 space 时不是数据,它是一个文件结构标记,通常不会在您的输出计数中找到它自己,但是因为我们使文件二进制顺序,它不会在运行时从读取中删除,因此如果您看到 LOW-VALUE 或 x '00' 后跟一个值小于 x'20" 的字符,然后将输出字节数减少 1。