在十六进制字节和字符串之间转换
我相信这个问题的解决办法很简单,但我在网上找不到答案。可能是我搜索的方法不对。
我想在Python中方便地在字符和它的二进制、十六进制表示之间切换。通常我这样做:
如果我有一个字符,比如说 chr(97),也就是字母 "a",我可以通过以下方式得到它的二进制表示:
byte_character=chr(97).encode()
或者得到它的十六进制表示:
hex_character=chr(97).encode().hex()
如果我想把它们转换回去,可以使用:
bytes.fromhex(hex_character).decode()
byte_character.decode()
这样对大多数字符都能正常工作,但有些字符的编码会用到多个字节。例如,chr(140)
编码后会变成两个字节:
chr(140).encode()
结果是:
b'\xc2\x8c'
而不是我预期的 b'\x8c'
。你能告诉我我哪里做错了吗?
2 个回答
UTF-8是一种编码方式,通常是默认使用的,除非你特别指定其他的编码。它会把任何大于128(也就是0x7F)的Unicode字符用两个或更多字节来表示。所以当你用chr(x)得到的结果大于128时,它会返回两个或更多的字节。
要解决这个问题,有两种方法。
第一种是使用'latin1'编码,这样可以让它在0到255的范围内返回1个字节。
x = chr(140)
byte = x.encode('latin1')
print(x)
>>> b'\x8c'
第二种方法是Python有一个内置函数叫to_bytes。使用这个方法时,不需要提前转换数字。你还可以在第一个参数中指定想要返回的字节数。
x = 140
byte = x.to_bytes(1, 'little')
print(byte)
>>> b'\x8c'
这两种方法都可以很好地解决你想要实现的功能。
如果你只需要处理0到255这个范围的字节,可以使用latin1
编码,也叫做ISO-8859-1编码。
>>> chr(140).encode('latin1')
b'\x8c'
>>> chr(255).encode('latin1')
b'\xff'
>>> chr(256).encode('latin1')
UnicodeEncodeError: 'latin-1' codec can't encode character '\u0100' in position 0: ordinal not in range(256)
你之前的尝试是默认使用UTF-8
编码,这种编码对于127以上的字符会使用多个字节来表示。
>>> chr(140).encode()
b'\xc2\x8c'
>>> chr(127).encode()
b'\7f'
>>> chr(128).encode()
b'\xc2\x80'
>>> chr(12345).encode()
b'\xe3\x80\xb9'