我在猜测,但看起来您可能正在将文件中的可变长度记录读取到固定长度的 COBOL 记录中。COBOL 记录末尾的垃圾让您有些悲伤。很难说垃圾从一次读取到下一次读取的一致性如何(超出实际输入记录长度范围的数据在技术上是未定义的)。那个垃圾最终被包括在WS_AMOUNT_TXT
之后UNSTRING
有很多方法可以解决这个问题。我在这里给你的建议可能不是最佳的,但它很简单,应该可以完成工作。
您的语句中的最后一个INTO
字段是接收所有尾随垃圾的字段。那个垃圾需要去掉。知道最后一个字段中唯一有效的字符是数字和十进制字符,您可以按如下方式对其进行清理:WS_AMOUNT_TXT
UNSTRING
PERFORM VARYING WS_I FROM LENGTH OF WS_AMOUNT_TXT BY -1
UNTIL WS_I = ZERO
IF WS_AMOUNT_TXT(WS_I:1) IS NUMERIC OR
WS_AMOUNT_TXT(WS_I:1) = '.'
MOVE ZERO TO WS_I
ELSE
MOVE SPACE TO WS_AMOUNT_TXT(WS_I:1)
END-IF
END-PERFORM
上面代码中的基本思想是从最后一个UNSTRING
输出字段的末尾扫描到开头,用空格替换任何不是有效数字或小数点的内容。一旦找到一个有效的数字/小数,假设其余的都是有效的,就退出循环。
清理后,使用我对上一个问题NUMVAL
的回答中概述的内在函数
将 WS_AMOUNT_TXT 转换为数字数据类型。
最后一条建议,MOVE SPACES TO INPUT_REC
在每次READ
删除之前读取可能留在缓冲区中的数据之前。这将在读取“长”记录之后的非常“短”记录时保护您 - 否则您可能会绊倒前一次读取留下的数据。
希望这可以帮助。
编辑刚刚注意到这个关于读取可变长度文件的问题的答案。使用可变长度输入记录是一种更好的方法。给定实际的输入记录长度,您可以执行以下操作:
UNSTRING INPUT_REC(1:REC_LEN) INTO...
之后为文件REC_LEN
指定的变量在哪里。您遇到的所有垃圾都发生在由定义的记录结束之后。使用如上图所示的引用修改将其修剪掉,然后再分离出各个数据字段。OCCURS DEPENDING ON
INPUT_REC
FD
REC_LEN
UNSTRING
编辑 2:
不能使用参考修改UNSTRING
。该死... 其他一些 COBOL 方言可以,但 OpenVMS COBOL 则不行。尝试以下操作:
MOVE INPUT_REC(1:REC_LEN) TO WS_BUFFER
UNSTRING WS_BUFFER INTO...
哪里WS_BUFFER
是一个足够长的工作存储PIC X
变量来保存最长的输入记录。当您MOVE
将短的字母数字字段转换为较长的字段时,目标字段左对齐,空格用于填充剩余空间(即。WS_BUFFER
)。由于函数可以接受前导和尾随空格,NUMVAL
因此您可以完全满足您的需要。
我有理由把你推向这个方向。读取短记录时,任何在记录缓冲区尾端结束的垃圾都是未定义的。有些垃圾有可能最终成为数字或小数点。如果发生这种情况,我最初建议的清理例程将失败。
编辑 3:
生成的 WS_AMOUNT_TXT 中没有 ^@,但仍然有 ^M
看起来文件系统将每条记录末尾的 <CR> (那个 ^M 东西)视为数据。
如果您正在阅读的文件来自 Windows 平台,而您现在正在 UNIX 平台上阅读它,则可以解释该问题。在 Windows 下,记录以 <CR><LF> 结束,而在 UNIX 上,它们仅以 <LF> 结束。UNIX 文件系统将 <CR> 视为记录的一部分。
如果是这种情况,您可以非常确定在每条读取记录的末尾都会有一个 <CR>。有很多方法可以解决这个问题:
方法 1:正如您已经指出的,在通过 COBOL 程序进行处理之前,使用 Notepad++ 或其他一些工具对文件进行预编辑以删除 <CR> 字符。就个人而言,我认为这不是最好的方法。我更喜欢仅使用 COBOL 解决方案,因为它涉及的处理步骤更少。
方法 2:在处理之前修剪每个输入记录的最后一个字符。最后一个字符应始终为 <CR>。如果您正在以可变长度读取记录并且具有可用的实际输入记录长度,请尝试以下操作。
SUBTRACT 1 FROM REC_LEN
MOVE INPUT_REC(1:REC_LEN) TO WS_BUFFER
UNSTRING WS_BUFFER INTO...
方法3:在UNSTRINGing时把<CR>当作分隔符,如下:
UNSTRING INPUT_REC DELIMITED BY "," OR x"0D"
INTO WS_ID_1, WS_ID_2, WS_CODE, WS_DESCRIPTION, WS_FLAG, WS_AMOUNT_TXT
方法 4:通过用空格替换尾随的非数字/非小数点字符来调整来自 UNSTRING 的最后一个接收字段。我在这个问题的前面稍微概述了这个解决方案。您还可以使用选项(格式 2)探索INSPECT
语句。REPLACING
这应该能够做几乎相同的事情 - 只需将所有 x"00" 替换为 SPACE,将 x"0D" 替换为 SPACE。
有志者,事竟成。上述任何解决方案都应该适合您。选择一个你最舒服的。