【问题标题】:Python byte representation of a hex string that is EBCDICEBCDIC 十六进制字符串的 Python 字节表示
【发布时间】:2018-08-07 07:49:33
【问题描述】:

我有一个十六进制字符串:

Hex = 'E388854083969497A4A38599408881A2409985829696A38584408699969440814082A48783888583924B'

作为一个字节对象,它看起来像这样:

b'\xe3\x88\x85@'b'\xe3\x88\x85@\x83\x96\x94\x97\xa4'b'\xe3\x88\x85@'b'\xe3\x88\x85@\x83\x96\x94\x97\xa4'b'\xe3\x88\x85@\x83'b'\xe3\x88'b'\xe3\x88\x85@\x83\x96\x94\x97\xa4'

在 EBCDIC 中是这样的:

The computer has rebooted from a bugcheck.

所以我知道十六进制 40 (x40) 在 EBCDIC 中是一个“空格”,在 ASCII 中是一个“@”

我不明白为什么 python 在打印字节对象时打印 '@' 而不是 '\x40'

我的测试代码示例是:

import codecs
Hex = 'E388854083969497A4A38599408881A2409985829696A38584408699969440814082A48783888583924B'

output = []
DDF = [4,9,4,9,5,2,9]
distance = 0

# This breaks my hex string into chunks based off the list 'DDF'
for x in DDF:
    output.append(Hex[distance:x*2+distance])
    distance += x*2

#This prints out the list of hex strings
for x in output:
    print(x)

#This prints out they byte objects in the list
for x in output:
    x = codecs.decode(x, "hex")
    print(x)

#The next line print the correct text
Hex = codecs.decode(Hex, "hex")
print(codecs.decode(Hex, 'cp1140'))

上面的输出是:

E3888540
83969497A4A3859940
8881A240
9985829696A3858440
8699969440
8140
82A48783888583924B
b'\xe3\x88\x85@'
b'\x83\x96\x94\x97\xa4\xa3\x85\x99@'
b'\x88\x81\xa2@'
b'\x99\x85\x82\x96\x96\xa3\x85\x84@'
b'\x86\x99\x96\x94@'
b'\x81@'
b'\x82\xa4\x87\x83\x88\x85\x83\x92K'
The computer has rebooted from a bugcheck.

所以我想我的问题是如何让 python 将字节对象打印为“x40”而不是“@”

非常感谢您的帮助:)

【问题讨论】:

  • 您手动打印。

标签: python-3.x hex ebcdic


【解决方案1】:

我觉得你的字节数组有点不对劲。

根据this,需要使用'cp500'进行解码,例如:

my_string_in_hex = 'E388854083969497A4A38599408881A2409985829696A38584408699969440814082A48783888583924B'
my_bytes = bytearray.fromhex(my_string_in_hex)
print(my_bytes)

my_string = my_bytes.decode('cp500')
print(my_string)

输出:

bytearray(b'\xe3\x88\x85@\x83\x96\x94\x97\xa4\xa3\x85\x99@\x88\x81\xa2@\x99\x85\x82\x96\x96\xa3\x85\x84@\x86\x99\x96\x94@\x81@\x82\xa4\x87\x83\x88\x85\x83\x92K')
The computer has rebooted from a bugcheck.

当你打印字节数组时,它仍然会打印一个'@',但它实际上是 \x40 “在幕后”。这只是对象的__repr__()。由于此方法没有使用任何“decode”参数来正确解码,它只是创建一个“可读”字符串用于打印目的。

__repr__()repr() 是“就是这样”;它只是“对象的表示”而不是实际的对象。这并不意味着它实际上是一个“@”。我只是在打印时使用该字符。它仍然是一个字节数组,而不是一个字符串。

解码时,它将使用所选的代码页正确解码。

【讨论】:

  • 感谢您提供指向 __repr__() 的链接。我刚刚做了一个测试,打印出每个十六进制值的字节对象。所有具有 ascii 可打印字符的字符都由 ascii 字符表示。而不可打印的则按其字节格式显示。
  • 就cp500 vs cp1140而言,我只需要去看看一些古老的服务器。我认为它实际上会是 cp37,但我还不知道。
  • @Keanwood 是的,我相信你可以找到正确解码的编解码器,我选择了 cp500 作为示例。您需要选择要使用的编解码器。
【解决方案2】:

当通过print() 打印时,Python 总是首先尝试将十六进制解码为可打印(读取:ASCII)字符。如果您需要打印完整的十六进制字符串,请使用 binascii.hexlify():

Hex = 'E388854083969497A4A38599408881A2409985829696A38584408699969440814082A48783888583924B'

binascii.hexlify(codecs.decode(Hex,'hex'))

>>>> b'e388854083969497a4a38599408881a2409985829696a38584408699969440814082a48783888583924b'

【讨论】:

  • 你知道吗,为什么 python 只尝试解码 hex 40 和 hex 4B?哦,实际上这是有道理的。我会仔细检查我的 ASCII/EBCIDEC 图表。也许这些是该样本中仅有的两个 ASCII 可打印字符
  • 我刚刚检查过了。看起来 hex 40 和 hex 4B 是唯一具有可打印 ascii 0-127 值的值。
猜你喜欢
  • 1970-01-01
  • 2019-07-27
  • 2012-06-05
  • 1970-01-01
  • 1970-01-01
  • 2013-07-26
  • 2012-01-24
  • 2014-05-26
  • 2015-01-17
相关资源
最近更新 更多