发布于 2015-08-30 07:43:57 | 210 次阅读 | 评论: 0 | 来源: 网络整理

问题

你有一个字节字符串并想将它解压成一个整数。或者,你需要将一个大整数转换为一个字节字符串。


解决方案

假设你的程序需要处理一个拥有128位长的16个元素的字节字符串。比如:

data = b'x00x124Vx00xx90xabx00xcdxefx01x00#x004'

为了将bytes解析为整数,使用 int.from_bytes() 方法,并像下面这样指定字节顺序:

>>> len(data)
16
>>> int.from_bytes(data, 'little')
69120565665751139577663547927094891008
>>> int.from_bytes(data, 'big')
94522842520747284487117727783387188
>>>

为了将一个大整数转换为一个字节字符串,使用 int.to_bytes() 方法,并像下面这样指定字节数和字节顺序:

>>> x = 94522842520747284487117727783387188
>>> x.to_bytes(16, 'big')
b'x00x124Vx00xx90xabx00xcdxefx01x00#x004'
>>> x.to_bytes(16, 'little')
b'4x00#x00x01xefxcdx00xabx90xx00V4x12x00'
>>>

讨论

大整数和字节字符串之间的转换操作并不常见。 然而,在一些应用领域有时候也会出现,比如密码学或者网络。 例如,IPv6网络地址使用一个128位的整数表示。 如果你要从一个数据记录中提取这样的值的时候,你就会面对这样的问题。

作为一种替代方案,你可能想使用6.11小节中所介绍的struct模块来解压字节。 这样也行得通,不过利用struct模块来解压对于整数的大小是有限制的。 因此,你可能想解压多个字节串并将结果合并为最终的结果,就像下面这样:

>>> data
b'x00x124Vx00xx90xabx00xcdxefx01x00#x004'
>>> import struct
>>> hi, lo = struct.unpack('>QQ', data)
>>> (hi << 64) + lo
94522842520747284487117727783387188
>>>

字节顺序规则(little或big)仅仅指定了构建整数时的字节的低位高位排列方式。 我们从下面精心构造的16进制数的表示中可以很容易的看出来:

>>> x = 0x01020304
>>> x.to_bytes(4, 'big')
b'x01x02x03x04'
>>> x.to_bytes(4, 'little')
b'x04x03x02x01'
>>>

如果你试着将一个整数打包为字节字符串,那么它就不合适了,你会得到一个错误。 如果需要的话,你可以使用 int.bit_length() 方法来决定需要多少字节位来存储这个值。

>>> x = 523 ** 23
>>> x
335381300113661875107536852714019056160355655333978849017944067
>>> x.to_bytes(16, 'little')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: int too big to convert
>>> x.bit_length()
208
>>> nbytes, rem = divmod(x.bit_length(), 8)
>>> if rem:
... nbytes += 1
...
>>>
>>> x.to_bytes(nbytes, 'little')
b'x03Xxf1x82iTx96xacxc7cx16xf3xb9xcf...xd0'
>>>
最新网友评论  共有(0)条评论 发布评论 返回顶部

Copyright © 2007-2017 PHPERZ.COM All Rights Reserved   冀ICP备14009818号  版权声明  广告服务