上QQ阅读APP看书,第一时间看更新
1.5 字节到大整数的打包与解包
在实际应用中,我们有时需要将一个字节字符串解压成一个整数,或将一个大整数转换为一个字节字符串。
例如,要处理一个拥有16个128位长的元素的字节字符串,示例如下:
data = b'\x00\x124V\x00x\x90\xab\x00\xcd\xef\x01\x00#\x004'
为了将字节字符串解析为整数,使用int.from_bytes()方法指定字节顺序:
print(f'data len is: {len(data)}') print(int.from_bytes(data, 'little')) print(int.from_bytes(data, 'big'))
执行py文件,输出结果如下:
data len is: 16 69120565665751139577663547927094891008 94522842520747284487117727783387188
为了将一个大整数转换为字节字符串,可使用int.to_bytes()方法指定字节数和字节顺序,代码(pack_unpack.py)示例如下:
x = 94522842520747284487117727783387188 print(x.to_bytes(16, 'big')) print(x.to_bytes(16, 'little'))
执行py文件,输出结果如下:
b'\x00\x124V\x00x\x90\xab\x00\xcd\xef\x01\x00#\x004' b'4\x00#\x00\x01\xef\xcd\x00\xab\x90x\x00V4\x12\x00'
大整数和字节字符串之间的转换操作并不常见,仅在一些应用领域出现,比如密码学或者网络。如IPv6网络地址使用一个128位的整数表示。作为上述操作的一种替代方案,我们可能想使用struct模块来解压字节。这样也行得通,不过利用struct模块来解压字节对于整数的大小是有限制的。因此,我们可能想解压多个字节串并将结果合并为最终的结果,相关代码(pack_unpack.py)示例如下:
import struct hi, lo = struct.unpack('>QQ', data) print(hi, lo) print((hi << 64) + lo)
执行py文件,输出结果如下:
5124093560524971 57965157801984052 94522842520747284487117727783387188
字节顺序规则(little或big)仅仅指定了构建整数时字节的低位和高位排列方式,相关代码(pack_unpack.py)示例如下:
x = 0x01020304 print(x.to_bytes(4, 'big')) print(x.to_bytes(4, 'little'))
执行py文件,输出结果如下:
b'\x01\x02\x03\x04' b'\x04\x03\x02\x01'
如果试着将一个整数打包为字节字符串,会得到错误结果。如果需要的话,可以使用int.bit_length()方法来决定需要多少字节位存储这个值,相关代码(pack_unpack.py)示例如下:
x = 523 ** 23 print(x) print(x.bit_length()) nbytes, rem = divmod(x.bit_length(), 8) if rem: nbytes += 1 print(x.to_bytes(nbytes, 'little')) print(x.to_bytes(16, 'little'))
执行py文件,输出结果如下:
335381300113661875107536852714019056160355655333978849017944067 208 b'\x03X\xf1\x82iT\x96\xac\xc7c\x16\xf3\xb9\xcf\x18\xee\xec\x91\xd1\x98\xa2\xc8\xd9R\xb5\xd0' OverflowError: int too big to convert