2

我有一个混合了文本和数字字段的 cobol“磁带格式”转储。我正在将 C# 中的文件作为二进制数组(字节数组)读取。我有复印本,格式在文本字段上排列得很好。还有许多 COMP-3 字段。这些字段中的数据似乎与任何 BCD 格式都不匹配。我知道数据应该是什么,并且我有 COMP-3 的原始字节。我尝试先转换为 EBCDIC,但没有产生更好的结果。关于如何以其他方式在内部存储 COMP-3 编号的任何想法?以下是 PIC、原始数据和预期数字的三个示例。我知道我的字段位置是正确的,因为数字的两侧都有 alpha 数据,并且所有排列都正确。

第一个示例:字段的 PIC 为 9(9) COMP-3 数据有 5 个字节,十六进制值为 02 01 20 91 22 结果数据应为日期 (00CCYYMMDD)。这个特定的日期应该是 3-17-14。

第二个例子:字段的 PIC 是 S9(3) COMP-3 数据有 2 个字节,十六进制值是 0A 14 结果值应该在 900 到 999 之间 我的理解是“S”表示最后一个半字节应该是 0xC 或 0xD 来表示 + 或 -

第三个例子:字段的 PIC 是 S9(15)V99 COMP-3 数据有 9 个字节,十六进制值是 00 00 00 00 00 00 01 80 0C 结果值应该是 12.00

好的,感谢那些回应的人,因为他们为我指明了正确的方向。这确实是一个 ASCII/EBCDIC 表示问题。BCD 存储在 EBCDIC 中。使用 ASCII 到 EBCDIC 转换表会产生格式正确的 BCD 数字:

我用这个链接来映射数据:http ://shop.alterlinks.com/ascii-table/ascii-ebcdic-us.php

我的数据:0A 14 转换:25 3C(原来 253 是一个有效值,规范是错误的)C = +,一切都好

我的数据:01 80 0C(不包括前导零) 转换:01 20 0C 12.00 C = +,隐含 2 位格式,一切都好

我的数据:02 01 20 91 22 转换:02 01 40 31 7F 2014/03/17(F 是未使用的半字节),一切都很好

4

5 回答 5

3

没有这样的东西COBOL "tape format"尽管这个短语可能对给你数据的人意味着什么。

您的问题的线索是您可以阅读文本。将其连接到 EBCDIC 标记和您对 C# 的引用。

因此,您正在读取最初来自大型机的数据,很可能是 IBM 大型机,它使用 EBCDIC 而不是 ASCII。

COBOL 没有对 BCD 的本机支持。

某个善良的灵魂为您所做的是将数据从 EBCDIC“转换”为 ASCII。否则你甚至不会识别“文本”。

不幸的是,对于任何二进制或压缩十进制或浮点字段(你不会看到很多最后的字段,但它们是 COMP-1/COMP-2),这意味着“转换”意味着“可能加扰”,因为覆盖假设单个字节,具有简单的字节值,而所有这些字段都具有常规编码,通过多个字节或非 EBCDIC 值或两者兼而有之。

所以:COMP-3 PIC 9(9)。正如你所说,五个字节。它是无符号的,所以最右边的 nybble 将是 F(所有位都打开)。由于符号位置被占用,即使是无符号字段,您的位置也会略微偏离。

在大型机上,它包含一个值X'020140317F'。只有该字段的整体才能对其价值有意义。但是,EBCDIC 到 ASCII 的转换使其变为 X'0201209122'。

如何?

查找 和 的 EBCDICX'02'X'01'。他们不会改变。查找 的值X'40',哎呀,这是一个空格,将其更改为 ASCII X'20'。查找 的值X'31'。实际上那里没有什么特别的,它已经转换为高于 的东西X'7F',但是如果您查看使用的翻译表,我想您会明白为什么会发生这种情况。这X'7F'是一个双引号,所以被改为X'22'.

您显示的其他值也存在同样的问题。

您应该只从大型机中以纯字符格式获取数据。这方面有很多答案,你应该看related右边的。

看看这个最近的问题:Convert COMP and COMP-3 Packed Decimal into readable value with C

于 2014-04-02T14:08:15.663 回答
2

好的,让我们看一下您的第一个示例。给定原始 BCD 内容的格式和值应该类似于

02 01 40 31 7F

在将其从 EBCDIC 转换为 ASCII 时,我们遇到了第一个、第二个和第四个字节的问题,因为它们是控制字符 - 所以在这里我们需要更多关于 ASCII->EBCDIC 转换器如何工作的细节。查看剩余的两个字节,这些字节将被更改

EBCDIC     ASCII     CHARACTER
40      -> 20        (blank)
7F      -> 22         "

因此,假设前两个字节保持不变,而第三个字节像31->91我们最终得到的那样进行转换

02 01 20 91 22

这就是你得到的。所以看起来发生了某种 EBCDIC->ASCII 转换。如果是这种情况,您可能无法修复数据,因为转换可能不是一对一的,因此不可逆。

查看第二个示例并使用

EBCDIC     ASCII     CHARACTER
25      -> 0A        (LF)
3C      -> 14        (DC4)

你会从25 3C适合格式但不适合你给出的范围开始。

在第三个示例中,原始01 20 0C可以转换为,01 80 0C因为20它也是一个没有直接 ASCII 等效的 EBCDIC 控制字符。

但是鉴于所有其他示例,我会假设存在一些代码页转换问题。如果您使用某种文件传输从(假定的)大型机中移动数据,请确保将其设置为二进制模式,并且在将文件拆分为字段并知道什么是字符之前不要进行任何字符转换什么不是。

编辑:您可以在此处找到几个 EBCDIC 和基于 ASCII 的代码页的列表,或者在此处查找一个pdf 相同的代码页。

于 2014-04-02T14:00:19.200 回答
1

我来晚了,但有一些建议可能会让你的生活更轻松......

首先,看看你是否可以让你的主机在下载之前将所有非字符(即二进制数字和压缩十进制)数据转换为显示格式(例如 PIC X)。然后,您只需要处理表示 0 到 9 的数字字符的“可打印”范围。仅可打印字符的代码页转换是相当标准的,并且不会搞砸太多。对于精通大型机环境的任何人来说,根据字帖重新格式化数据并不是一个困难的前景。不幸的是,有时您会遇到“迂回”,并声称它非常昂贵,或者需要特殊软件,或者其他一百个虚假借口中的任何一个。

如果你得到“runaround”,那么下一个最好的办法是以二进制格式下载文件,并对字符数据进行自己的代码页转换(相当直接)。接下来根据您的字帖定义处理二进制数据。使用一些谷歌,您应该能够找到足够的信息来将 PACKED-DECIMAL (COMP-3) 数据转换为您需要的任何数据。

这里有几个链接可以帮助您入门:

数值数据格式

压缩十进制

我不建议尝试对文件传输包应用的代码页转换进行逆向工程,以解码打包的十进制和其他二进制数据。

于 2014-04-02T18:03:43.347 回答
0

好的,感谢两位回应的人,因为他们为我指明了正确的方向。这确实是一个 ASCII/EBCDIC 表示问题。BCD 存储在 EBCDIC 中。使用 ASCII 到 EBCDIC 转换表会产生格式正确的 BCD 数字:

我用这个链接来映射数据:http ://shop.alterlinks.com/ascii-table/ascii-ebcdic-us.php

My data:    0A 14
Converted:  25 3C  (turns out that 253 is a valid value, spec was wrong) C = +, all good

My data:    01 80 0C  (excluding leading zeros)
Converted:  01 20 0C  12.00  C = +, implied 2 digits in format, all good

My data:    02 01 20 91 22
Converted:  02 01 40 31 7F     2014/03/17  (F is unused nibble), all good

再次感谢上述两个答案,它们使我朝着正确的方向前进。

于 2014-04-02T17:45:05.253 回答
-1

您可以通过将数据转换为一种现代的数据传输方法来避免上述问题:XML。

于 2014-04-24T23:23:07.333 回答