【发布时间】:2009-05-10 20:24:01
【问题描述】:
我有一个非负整数,我想有效地将它转换为包含相同数据的大端字符串。例如,int 1245427(即 0x1300F3)应生成一个长度为 3 的字符串,其中包含三个字节值分别为 0x13、0x00 和 0xf3 的字符。
我的整数是 35 (base-10) 位数。
我该怎么做?
【问题讨论】:
标签: python
我有一个非负整数,我想有效地将它转换为包含相同数据的大端字符串。例如,int 1245427(即 0x1300F3)应生成一个长度为 3 的字符串,其中包含三个字节值分别为 0x13、0x00 和 0xf3 的字符。
我的整数是 35 (base-10) 位数。
我该怎么做?
【问题讨论】:
标签: python
在 Python 3.2+ 中,您可以使用int.to_bytes:
>>> n = 1245427
>>> n.to_bytes((n.bit_length() + 7) // 8, 'big') or b'\0'
b'\x13\x00\xf3'
>>> (1245427).to_bytes(3, byteorder='big')
b'\x13\x00\xf3'
【讨论】:
signed=True。
(length + 7) // 8 部分与math.ceil(length / 8) 相同吗?如果是这样,我认为使用该选项会更清楚
n.bit_length() 的大小合理(您需要大约千万亿位才能出现问题,这意味着n 将是难以置信的大)。在我的情况下,可读性比性能提升更重要,而且数字永远不会那么大。
您可以使用struct 模块:
import struct
print(struct.pack('>I', your_int))
'>I' 是一个格式字符串。 > 表示大端,I 表示无符号整数。查看文档以获取更多格式字符。
【讨论】:
int 类型,但即使在 Python 2.4+ 中,ints 在溢出 32 位(有符号)时也会自动转换为 Python longs。
这速度很快,适用于小型和(任意)大型整数:
def Dump(n):
s = '%x' % n
if len(s) & 1:
s = '0' + s
return s.decode('hex')
print repr(Dump(1245427)) #: '\x13\x00\xf3'
【讨论】:
if len(s) & 1 替换为if len(s) % 2(如果有奇数个十六进制字符,则两者都是真的),并且'%x' % n 替换为'{0:x}'.format(n)(两者都是其中将数字格式化为十六进制字符串)。
可能最好的方法是通过内置的struct module:
>>> import struct
>>> x = 1245427
>>> struct.pack('>BH', x >> 16, x & 0xFFFF)
'\x13\x00\xf3'
>>> struct.pack('>L', x)[1:] # could do it this way too
'\x13\x00\xf3'
或者——我通常不推荐这个,因为它容易出错——你可以通过 shift 和 chr() 函数“手动”完成它:
>>> x = 1245427
>>> chr((x >> 16) & 0xFF) + chr((x >> 8) & 0xFF) + chr(x & 0xFF)
'\x13\x00\xf3'
出于好奇,为什么只需要三个字节?通常你会将这样一个整数打包成一个完整的 32 位(C unsigned long),然后使用 struct.pack('>L', 1245427) 但跳过 [1:] 步骤?
【讨论】:
def tost(i):
result = []
while i:
result.append(chr(i&0xFF))
i >>= 8
result.reverse()
return ''.join(result)
【讨论】:
基于@pts' answer的单源Python 2/3兼容版本:
#!/usr/bin/env python
import binascii
def int2bytes(i):
hex_string = '%x' % i
n = len(hex_string)
return binascii.unhexlify(hex_string.zfill(n + (n & 1)))
print(int2bytes(1245427))
# -> b'\x13\x00\xf3'
【讨论】:
我认为最短的方法如下:
import struct
val = 0x11223344
val = struct.unpack("<I", struct.pack(">I", val))[0]
print "%08x" % val
这会将整数转换为字节交换整数。
【讨论】:
使用bitstring 模块:
>>> bitstring.BitArray(uint=1245427, length=24).bytes
'\x13\x00\xf3'
请注意,对于此方法,您需要指定您正在创建的位串的长度。
在内部,这与 Alex 的回答几乎相同,但如果您想对数据做更多事情,该模块还有很多额外的功能可用。
【讨论】:
使用 pwntools 非常容易,这是为软件黑客创建的工具
(讽刺的是,我偶然发现了这个线程并在这里尝试了解决方案,直到我意识到 pwntools 中存在转换功能)
import pwntools
x2 = p32(x1)
【讨论】: