3

我有一个以前是 EBCDIC 编码文件的文件,它使用dd转换为 ASCII 。但是,有些行包含我想阅读的 COMP-3 压缩字段。

例如,我想解码的行之一的字符串表示是:

'15\x00\x00\x00\x04@\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x0c777093020141204NNNNNNNNYNNNN\n'

我要读取的字段由 指定PIC S9(09) COMP-3 POS. 3,即从第三个字节开始的字段,解码时长九个字节(因此,根据COMP-3 规范,编码时长五个字节)。

我了解 COMP-3 规范,并且我也知道对于这一特定行,该字段的整数值应该是315,但我不知道要做什么才能实际解码该字段。我也不确定将文件转换dd为 ASCII 的事实是否存在问题。

以前有没有人研究过类似的问题,或者我有什么明显的遗漏?谢谢!

4

3 回答 3

1

是的,文件包含非字符数据并且已在文件或记录级别从 EBCDIC 转换为 ASCII 是一个问题。使用什么工具来做到这一点不是问题。

到目前为止,对您来说最简单的事情是要求仅以字符形式向您提供数据。如果数据包含带符号的字段,则符号应该是单独的,并且如果有隐含的小数位,这些应该是实际的,或者由缩放值指示(以您更方便的为准)。

然后你不需要转换任何东西。我永远无法理解人们如何认为他们可以只给你包含“任何东西”的 EBCDIC 数据并期望你把它整理出来。

如果您单击 EBCDIC 标签,您会发现一些其他解决方案,如果由于某些愚蠢的原因,无法从 EBCDIC 源获得字符数据,您可以应用这些解决方案。既然他们已经给你废话了,他们可能会想出一些愚蠢的理由。如果是这样,请将其(礼貌地)记录给您的老板。

如果你得到字符数据,那么你可以 dd 或任何东西来转换它(如果你仍然得到看起来很有趣的东西,请检查代码页)。

如果您转换非字符数据,事情会被腌制的原因如下:

05  a-packed-decimal-positive-five COMP-3 PIC S9 VALUE +5.
05  a-character-asterisk PIC X VALUE "*".

在 EBCDIC 中,这两者都具有十六进制值5C。两者都将转换为 ASCII 星号。COMP-3 的值 5 随即丢失。请注意,COMP-3 可以在低位符号之外为其每个字节取任意一对数字。碰巧碰到控制角色时腌制。“二进制”字段也是如此,更糟糕的是因为意外命中的可能性更大。

于 2015-04-04T13:48:00.747 回答
0

如果要进行逆字符编码转换,则可以确定该;因为有 [很好的理由] 对此表示怀疑,所以最好的做法是按照 Bill Woodger 的建议,获取文本格式的数据的新副本,或者获取原始数据的新副本,但不要破坏具有固有二进制[部分]数据的字符翻译的数据。在这种特定情况下,我相信该值是可确定的;但作为 0d377 (+377) 而不是 0d315 (+315)。
希望可以理解以下几点:

ASCII 字符串(给定\xEncoded):

'15\x00\x00\x00\x04@\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x0c777093020141204NNNNNNNNYNNNN\n'

ASCII(十六进制):

  ....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+....9....+
X'31350000000440000000000C000000000C3737373039333032303134313230344E4E4E4E4E4E4E4E594E4E4E4E0A'
           -04-    ASCII x04->x37 in EBCDIC [control character End of Transmission (EOT)]
             -40-  ASCII x40->x7C in EBCDIC [or xB5 or x80 or xEC or ?? per @ is a variant character in EBCDIC]

EBCDIC:

  ....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+....9....+
x'F1F5000000377C000000000C000000000CF7F7F7F0F9F3F0F2F0F1F4F1F2F0F4D5D5D5D5D5D5D5D5E8D5D5D5D525'
           -37-    EBCDIC x37->x04 in ASCII [control character End of Transmission (EOT)]
             -7C-  EBCDIC x7C->x40 in ASCII [or A7 or 25 or ?? per x7C does not represent an invariant character in EBCDIC]

中的数据字节PIC S9(09) COMP-3 POS. 3是压缩二进制编码十进制 (BCD),从位置 5 到 14 的五个字节 [在所示的比例线中;十进制数字000000377C],表示正十进制整数值377。我毫不怀疑,那是原始价值。

偶然地,对于该特定字符串,从 EBCDIC 到 ASCII 的转换并未因无法往返字符转换而损坏。记录中接下来的两个值也可能定义相同,并且在与 EBCDIC 之间的转换中,这些值也不受数据丢失的影响;即带有代码点x0C 的控制字符在EBCDIC 和ASCII 中是相同的,并且都具有正零的十进制值。

虽然可能有其他可能的代码页可供尝试往返,但 CP00037 提供了强有力的竞争者 [x7C 具有有效的符号半字节] 和有效的转换;的值315似乎不太可能,因为保留的EBCDIC 控制字符 x31 必须转换为 ASCII x04 而不是 x91 或 xBA,并且最有可能的 EBCDIC x5C 莫名其妙地必须转换为 ASCII x40 而不是 x2A [或负值 x5D 莫名其妙地转换为 ASCII x40 而不是 x29;没有考虑任何非首选的标牌可能性],这两者都没有任何意义。

于 2015-05-20T01:25:34.913 回答
0

经过大量的试验和错误,我注意到,直接编码为 Ascii 格式将产生正确的数字,除了最后一个数字和符号。有一个转换表可以对最后一位进行转换。这是我使用一些适用于我的用例的快速而肮脏的代码所做的。我的文件被加载到 pandas 的数据框中,我正在调用此函数通过传入值和小数位数来为我进行翻译。

sign = {'{': 1,'A': 1,'B': 1,'C': 1,'D': 1,'E': 1,'F': 1,'G': 1,'H': 1,'I': 1,'}': -1,'J': -1,'K': -1,
'L': -1,'M': -1,'N': -1,'O': -1,'P': -1,'Q': -1,'R': -1 }

last_digit = {'{': 0,'A': 1,'B': 2,'C': 3,'D': 4,'E': 5,'F': 6,'G': 7,'H': 8,'I': 9,'}': 0,'J': 1,'K': 2,
'L': 3,'M': 4,'N': 5,'O': 6,'P': 7,'Q': 8,'R': 9 }

def unpack(value,decimal):

    l = value.str[-1:]
    s = l.map(sign)
    d = l.map(last_digit)
    num = value.str[:-1]
    return (num.apply(int)*10+d)*s/10**decimal

现在您在数据框中的新字段可以是:

df['unpacked'] = unpack(df['Packed'],2)
于 2019-08-22T19:40:12.100 回答