在python中将ebcdic解码为ASCII /可读文本

时间:2019-04-14 11:00:21

标签: python-3.x encoding utf-8 ascii ebcdic

我有一个用“ cp500”编码的IBM大型机文件(已被告知),该文件将被解码为ascii或可读文本。该文件是使用IPSwitch工具从unix服务器传输到Windows的。

我已经尝试了以下代码,但无法实现我想要的:

sample data = 'ðñðòðõÅäù@@@@@@@ððð :BÄÑðò÷øò@@@JaÈK' - in txt file

import codecs

with open(file, "rb") as ebcdic:
    ascii_txt = codecs.decode(ebcdic, "cp500")
    print(ascii_txt)

这会产生类型错误

"TypeError: decoding with 'cp500' codec failed (TypeError: a bytes-
like object is required, not '_io.BufferedReader')"

然后我尝试了这两个,

with open(file, 'r', encoding='cp500') as f:
    for line in f:
        print(line)

with codecs.open(file, 'r', encoding='cp500')
    for line in f:
        print(line)

我还尝试了国际编码“ cp1140”格式-

with open(file, 'r', encoding="cp1140") as f:
    for line in f:
       print(line)

我希望得到可读的输出-抄写本布局-这样的东西...

0001***********
0002...........
0003...........

但是以上三个都将输出打印为:

C¢C£C¢C¥C¢C§CeCuC¾       C¢C¢C¢âCdCjC¢C¥C¼C½C¥   [/Ch.

我还尝试以“ rb”模式读取文件:

with open(file, 'rb') as f:
    for line in f:
        print(line)

这将产生以下输出-

b'\xc3\xb0\xc3\xb1\xc3\xb0\xc3\xb2\xc3\xb0\xc3\xb5\xc3\x85\xc3\xa4\xc3\xb9@@@@@@@\xc3\xb0\xc3\xb0\xc3\xb0 :B\xc3\x84\xc3\x91\xc3\xb0\xc3\xb2\xc3\xb7\xc3\xb8\xc3\xb2@@@Ja\xc3\x88K'

这是我第一次处理ebcdic /大型机文件-解码方面的任何帮助将不胜感激!

先谢谢了:)

1 个答案:

答案 0 :(得分:0)

我怀疑EBCDIC数据已用Latin-1解码并以UTF-8保存在您当前使用的TXT文件中。

让我们尝试使用示例的缩写版本进行重构:

>>> copybook = '0102 [/H.'

这是最初生产的。 该文本使用EBCDIC编码:

>>> '0102 [/H.'.encode('cp500')
b'\xf0\xf1\xf0\xf2@Ja\xc8K'

这就是原始主机文件中写入的字节序列。 您也可以使用一般(非Python)表示形式来编写它:

F0 F1 F0 F2 40 4A 61 C8 4B

现在,这些字节已使用Latin-1或CP-1252(“ Windows Latin-1”)解码。 如果在Windows计算机上执行此操作,可能会发生以下情况:

>>> with open(file) as f:
...     text = f.read()
>>> text
'ðñðò@JaÈK'

您可以像这样模拟这种误编码:

>>> '0102 [/H.'.encode('cp500').decode('latin1')
'ðñðò@JaÈK'

这是您在帖子开头显示的字符串。 这已经比仅处理大型机文件的问题更糟糕了,这是大型机文件的莫吉克烤!

现在,更糟糕的是,该字符串已使用UTF-8保存到文件中。 我们也尝试一下:

>>> '0102 [/H.'.encode('cp500').decode('latin1').encode('utf8')
b'\xc3\xb0\xc3\xb1\xc3\xb0\xc3\xb2@Ja\xc3\x88K'

根据最后一个片段(您在'rb'模式下打开并打印输出),这些是TXT文件中包含的字节。

现在这些字节不再是有效的EBCDIC。 Latin-1和UTF-8的编码往返会扭曲内容:

>>> '0102 [/H.'.encode('cp500').decode('latin1').encode('utf8').decode('cp500')
'C¢C£C¢C¥ [/Ch.'

这是您在问题中所示的第一次尝试中得到的输出。

为了从情况中恢复过来,您需要消除失真:

>>> distorted = '0102 [/H.'.encode('cp500').decode('latin1').encode('utf8')
>>> distorted
b'\xc3\xb0\xc3\xb1\xc3\xb0\xc3\xb2@Ja\xc3\x88K'
>>> recovered = distorted.decode('utf8').encode('latin1').decode('cp500')
>>> recovered
'0102 [/H.'

...或从文件中读取时,您可以让open为您执行第一步解码:

>>> with open(file, encoding='utf8') as f:
...     data = f.read()
...     text = data.encode('latin1').decode('cp500')

对于完整的示例行,将产生以下文本:

'010205EU9       000\x80\x9aâDJ02782   [/H.'

我不是100%确信这是原文。 它包含一些控制字符(809A)和非ASCII字母(“â”)。 也许000...782块必须被解释为二进制blob。 但我希望这种分析可以帮助您进一步解决这个问题!