将一串字节转换为一个int(python)
如何将一个字节的string转换为Python中的int?
像这样说: 'y\xcc\xa6\xbb'
我想出了一个聪明/愚蠢的做法:
sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))
我知道必须有内置的东西,或在标准的库,这更简单地…
这不同于转换可以使用int(xxx,16) 的hex数字的string ,但是我想要转换一串实际的字节值。
更新:
我有点像詹姆斯的回答好一点,因为它不需要导入另一个模块,但格雷格的方法更快:
>>> from timeit import Timer >>> Timer('struct.unpack("<L", "y\xcc\xa6\xbb")[0]', 'import struct').timeit() 0.36242198944091797 >>> Timer("int('y\xcc\xa6\xbb'.encode('hex'), 16)").timeit() 1.1432669162750244
我的哈克法:
>>> Timer("sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))").timeit() 2.8819329738616943
进一步更新:
有人问道在导入另一个模块时会遇到什么问题。 那么导入一个模块不一定便宜,看看:
>>> Timer("""import struct\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""").timeit() 0.98822188377380371
包括导入模块的成本几乎否定了这种方法所具有的所有优点。 我相信这只会包括在整个基准testing期间import一次的费用; 看看我每次强制重新加载时会发生什么情况:
>>> Timer("""reload(struct)\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""", 'import struct').timeit() 68.474128007888794
毋庸置疑,如果你对这个方法每进行一次执行很多次,那么这个问题的成功率就会小得多。 这也可能是I / O成本,而不是CPU,所以它可能取决于特定机器的容量和负载特性。
你也可以使用结构模块来做到这一点:
>>> struct.unpack("<L", "y\xcc\xa6\xbb")[0] 3148270713L
在Python 3.2及更高版本中,使用
>>> int.from_bytes(b'y\xcc\xa6\xbb', byteorder='big') 2043455163
要么
>>> int.from_bytes(b'y\xcc\xa6\xbb', byteorder='little') 3148270713
根据你的字节串的字节顺序 。
这也适用于任意长度的string整数,以及通过指定signed=True
来表示两个补码有符号整数。 查看from_bytes
的文档 。
正如Greg所说的,如果你正在处理二进制值,你可以使用struct,但是如果你只是有一个“hex数字”,但是以字节格式,你可能只想把它转换为:
s = 'y\xcc\xa6\xbb' num = int(s.encode('hex'), 16)
…这是一样的:
num = struct.unpack(">L", s)[0]
…除了它可以工作任何数量的字节。
import array integerValue = array.array("I", 'y\xcc\xa6\xbb')[0]
警告:以上是强烈平台特定的。 “I”说明符和string-> int转换的字节序都依赖于您的特定Python实现。 但是,如果您想要一次转换多个整数/string,那么arrays模块会快速执行。
我使用以下函数在int,hex和bytes之间转换数据。
def bytes2int(str): return int(str.encode('hex'), 16) def bytes2hex(str): return '0x'+str.encode('hex') def int2bytes(i): h = int2hex(i) return hex2bytes(h) def int2hex(i): return hex(i) def hex2int(h): if len(h) > 1 and h[0:2] == '0x': h = h[2:] if len(h) % 2: h = "0" + h return int(h, 16) def hex2bytes(h): if len(h) > 1 and h[0:2] == '0x': h = h[2:] if len(h) % 2: h = "0" + h return h.decode('hex')
资料来源: http : //opentechnotes.blogspot.com.au/2014/04/convert-values-to-from-integer-hex.html
在Python 2.x中,可以使用格式说明符<B
表示无符号字节, <b
表示带有struct.unpack
/ struct.pack
带符号字节。
例如:
令x
= '\xff\x10\x11'
data_ints = struct.unpack('<' + 'B'*len(x), x) # [255, 16, 17]
和:
data_bytes = struct.pack('<' + 'B'*len(data_ints), *data_ints) # '\xff\x10\x11'
*
是必需的!
有关格式说明符的列表,请参阅https://docs.python.org/2/library/struct.html#format-characters 。
如果您的版本> = 3.2,int.from_bytes是最好的解决scheme。 “struct.unpack”解决scheme需要一个string,所以它不适用于字节数组。 这是另一个解决scheme:
def bytes2int( tb, order='big'): if order == 'big': seq=[0,1,2,3] elif order == 'little': seq=[3,2,1,0] i = 0 for j in seq: i = (i<<8)+tb[j] return i
hex(bytes2int([0x87,0x65,0x43,0x21]))返回“0x87654321”。
它处理大和小的字节顺序,可以容易地修改为8个字节
>>> reduce(lambda s, x: s*256 + x, bytearray("y\xcc\xa6\xbb")) 2043455163
testing1:反转:
>>> hex(2043455163) '0x79cca6bb'
testing2:字节数> 8:
>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAAA")) 338822822454978555838225329091068225L
testing3:增加一个:
>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAAB")) 338822822454978555838225329091068226L
testing4:追加一个字节,说'A':
>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAABA")) 86738642548474510294585684247313465921L
testing5:除以256:
>>> reduce(lambda s, x: s*256 + x, bytearray("AAAAAAAAAAAAAABA"))/256 338822822454978555838225329091068226L
如预期的那样,结果等于testing4的结果。
我正在努力寻找一个可以在Python 2.x下工作的任意长度字节序列的解决scheme。 最后我写了这个,这有点不好意思,因为它执行string转换,但它的工作原理。
Python 2.x的函数,任意长度
def signedbytes(data): """Convert a bytearray into an integer, considering the first bit as sign. The data must be big-endian.""" negative = data[0] & 0x80 > 0 if negative: inverted = bytearray(~d % 256 for d in data) return -signedbytes(inverted) - 1 encoded = str(data).encode('hex') return int(encoded, 16)
这个function有两个要求:
-
input
data
需要是一个bytearray
。 你可以这样调用函数:s = 'y\xcc\xa6\xbb' n = signedbytes(s)
-
数据需要是大端的。 如果你有一个little-endian的价值,你应该先倒过来:
n = signedbytes(s[::-1])
当然,只有在需要任意长度的情况下才能使用。 否则,坚持更多的标准方式(如struct
)。