如何在 python 中将具有不可打印字符的字节字符串转换为十六进制?
How to convert byte string with non-printable chars to hexadecimal in python?
我有一个 ANSI 字符串 Ď–ór˙rXüď\ő‡íQl7
,我需要像这样将它转换为十六进制:
06cf96f30a7258fcef5cf587ed51156c37
(用 XVI32 转换)。
问题是 Python 无法正确编码所有字符(其中一些甚至在这里,在 Stack Overflow 上显示不正确)所以我必须用字节字符串处理它们。
所以上面的字符串是以字节为单位的:b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\xf5\x87\xedQ\x15l7'
这就是我需要转换为十六进制的内容。
到目前为止我试过 binascii 没有成功,我试过这个:
h = ""
for i in b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\xf5\x87\xedQ\x15l7':
h += hex(i)
print(h)
它打印:
0x60xcf0x960xf30xa0x720x830xff0x720x580xfc0xef0x5c0xf50x870xed0x510x150x6c0x37
好的。看来我有所进展...但是 0x
是怎么回事?
当我像这样从字符串中删除 0x 时:
h.replace("0x", "")
我得到 6cf96f3a7283ff7258fcef5cf587ed51156c37
看起来是正确的。
但有时字节字符串在 x
旁边有一个 0
,它会从字符串中删除,从而导致不正确的十六进制字符串。 (上面的字符串开头缺少 0)。
有什么想法吗?
根据文档,hex()
将 “整数转换为前缀为‘0x’的小写十六进制字符串。”因此,当使用 hex()
时,您总是会得到一个 0x
前缀。如果你想连接多个十六进制表示,你将始终必须删除它。
But sometimes the byte string has a 0
next to a x
and it gets removed from the string resulting in a incorrect hexadecimal string. (the string above is missing the 0
at the beginning).
这没有任何意义。 x
不是有效的十六进制字符,因此在您的解决方案中,它 只能 由 hex()
调用生成。而且,如上所述,将始终创建一个 0x
。所以序列 0x
可以 never 在你的结果字符串中以不同的方式出现,所以用什么替换 0x
应该很好。
您的解决方案中的实际问题是 hex()
不强制使用两位数的结果,如以下示例所示:
>>> hex(10)
'0xa'
>>> hex(2)
'0x2'
所以在你的情况下,由于字符串以 b\x06
开头,代表数字 6
,hex(6)
仅 returns 0x6
,所以你只在这里得到一个数字,这是你问题的真正原因。
您可以做的是使用格式字符串执行到十六进制的转换。这样你既可以省略前缀又可以强制使用两位数的长度。然后,您可以使用 str.join
将其全部组合成一个十六进制字符串:
>>> value = b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\xf5\x87\xedQ\x15l7'
>>> ''.join(['{:02x}'.format(x) for x in value])
'06cf96f30a7283ff7258fcef5cf587ed51156c37'
此解决方案不仅适用于字节字符串,而且适用于任何可以格式化为十六进制字符串的内容(例如整数列表):
>>> value = [1, 2, 3, 4]
>>> ''.join(['{:02x}'.format(x) for x in value])
'01020304'
如果你是 运行 python 3.5+,bytes
类型有一个新的 bytes.hex()
方法,returns 字符串表示。
>>> h = b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\xf5\x87\xedQ\x15l7'
b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\xf5\x87\xedQ\x15l7'
>>> h.hex()
'06cf96f30a7283ff7258fcef5cf587ed51156c37'
否则你可以使用binascii.hexlify()
做同样的事情
>>> import binascii
>>> binascii.hexlify(h).decode('utf8')
'06cf96f30a7283ff7258fcef5cf587ed51156c37'
我有一个 ANSI 字符串 Ď–ór˙rXüď\ő‡íQl7
,我需要像这样将它转换为十六进制:
06cf96f30a7258fcef5cf587ed51156c37
(用 XVI32 转换)。
问题是 Python 无法正确编码所有字符(其中一些甚至在这里,在 Stack Overflow 上显示不正确)所以我必须用字节字符串处理它们。
所以上面的字符串是以字节为单位的:b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\xf5\x87\xedQ\x15l7'
这就是我需要转换为十六进制的内容。
到目前为止我试过 binascii 没有成功,我试过这个:
h = ""
for i in b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\xf5\x87\xedQ\x15l7':
h += hex(i)
print(h)
它打印:
0x60xcf0x960xf30xa0x720x830xff0x720x580xfc0xef0x5c0xf50x870xed0x510x150x6c0x37
好的。看来我有所进展...但是 0x
是怎么回事?
当我像这样从字符串中删除 0x 时:
h.replace("0x", "")
我得到 6cf96f3a7283ff7258fcef5cf587ed51156c37
看起来是正确的。
但有时字节字符串在 x
旁边有一个 0
,它会从字符串中删除,从而导致不正确的十六进制字符串。 (上面的字符串开头缺少 0)。
有什么想法吗?
根据文档,hex()
将 “整数转换为前缀为‘0x’的小写十六进制字符串。”因此,当使用 hex()
时,您总是会得到一个 0x
前缀。如果你想连接多个十六进制表示,你将始终必须删除它。
But sometimes the byte string has a
0
next to ax
and it gets removed from the string resulting in a incorrect hexadecimal string. (the string above is missing the0
at the beginning).
这没有任何意义。 x
不是有效的十六进制字符,因此在您的解决方案中,它 只能 由 hex()
调用生成。而且,如上所述,将始终创建一个 0x
。所以序列 0x
可以 never 在你的结果字符串中以不同的方式出现,所以用什么替换 0x
应该很好。
您的解决方案中的实际问题是 hex()
不强制使用两位数的结果,如以下示例所示:
>>> hex(10)
'0xa'
>>> hex(2)
'0x2'
所以在你的情况下,由于字符串以 b\x06
开头,代表数字 6
,hex(6)
仅 returns 0x6
,所以你只在这里得到一个数字,这是你问题的真正原因。
您可以做的是使用格式字符串执行到十六进制的转换。这样你既可以省略前缀又可以强制使用两位数的长度。然后,您可以使用 str.join
将其全部组合成一个十六进制字符串:
>>> value = b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\xf5\x87\xedQ\x15l7'
>>> ''.join(['{:02x}'.format(x) for x in value])
'06cf96f30a7283ff7258fcef5cf587ed51156c37'
此解决方案不仅适用于字节字符串,而且适用于任何可以格式化为十六进制字符串的内容(例如整数列表):
>>> value = [1, 2, 3, 4]
>>> ''.join(['{:02x}'.format(x) for x in value])
'01020304'
如果你是 运行 python 3.5+,bytes
类型有一个新的 bytes.hex()
方法,returns 字符串表示。
>>> h = b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\xf5\x87\xedQ\x15l7'
b'\x06\xcf\x96\xf3\nr\x83\xffrX\xfc\xef\\xf5\x87\xedQ\x15l7'
>>> h.hex()
'06cf96f30a7283ff7258fcef5cf587ed51156c37'
否则你可以使用binascii.hexlify()
做同样的事情
>>> import binascii
>>> binascii.hexlify(h).decode('utf8')
'06cf96f30a7283ff7258fcef5cf587ed51156c37'