将Python int转换为big-endian字节串

fis*_*ish 56 python

我有一个非负的int,我想有效地将​​它转换为包含相同数据的big-endian字符串.例如,int 1245427(0x1300F3)应该生成一个长度为3的字符串,其中包含三个字符,其字节值为0x13,0x00和0xf3.

我的整数是35(基数为10)的数字.

我该怎么做呢?

Aym*_*ieh 43

您可以使用struct模块:

import struct
print struct.pack('>I', your_int)
Run Code Online (Sandbox Code Playgroud)

'>I'是格式字符串.>表示大端,I表示unsigned int.查看文档以获取更多格式字符.

  • struct.pack返回一个固定长度的字符串,似乎没有处理大整数的工具.我想我可以将我的int分解为2 ^ 32的幂,通过struct.pack()运行它,并重新组合结果,但这似乎很多工作......你知道一个更简单的方法吗? (8认同)
  • 我找不到处理任意长整数的库。我认为你必须自己实现它。其他答案包含实现。 (2认同)
  • benhoyt,谢谢你的评论。我知道这一点。我说的是处理任意长整数到大字节序的转换。通常不处理它们。 (2认同)

Jan*_*sen 40

在Python 3.2+中,您可以使用int.to_bytes:

如果您不想指定大小

>>> n = 1245427
>>> n.to_bytes((n.bit_length() + 7) // 8, 'big') or b'\0'
b'\x13\x00\xf3'
Run Code Online (Sandbox Code Playgroud)

如果您不介意指定大小

>>> (1245427).to_bytes(3, byteorder='big')
b'\x13\x00\xf3'
Run Code Online (Sandbox Code Playgroud)

  • 如何在2.6中执行此操作? (11认同)
  • 如果您的整数已签名,请添加`signed = True`. (2认同)
  • 我认为 `(length + 7) // 8` 部分与执行 `math.ceil(length / 8)` 是一样的吗?如果是这样,我认为使用该选项会更清楚 (2认同)

pts*_*pts 13

这很快,适用于小型和(任意)大型整数:

def Dump(n): 
  s = '%x' % n
  if len(s) & 1:
    s = '0' + s
  return s.decode('hex')
print repr(Dump(1245427))  #: '\x13\x00\xf3'
Run Code Online (Sandbox Code Playgroud)

  • 作为上述的一种变体,可以将“if len(s) & 1”替换为“if len(s) % 2”(如果有奇数个十六进制字符,则两者都是正确的)和“%x” % n` 和 `'{0:x}'.format(n)`(两者都将数字格式化为十六进制字符串)。 (3认同)

Ben*_*oyt 7

可能最好的方法是通过内置的struct模块:

>>> 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'
Run Code Online (Sandbox Code Playgroud)

或者 - 我通常不推荐这个,因为它容易出错 - 你可以通过移动和chr()功能"手动"完成它:

>>> x = 1245427
>>> chr((x >> 16) & 0xFF) + chr((x >> 8) & 0xFF) + chr(x & 0xFF)
'\x13\x00\xf3'
Run Code Online (Sandbox Code Playgroud)

出于好奇,为什么你只想要三个字节?通常你将这样一个整数打包成一个完整的32位(一个C unsigned long),并使用struct.pack('>L', 1245427)但跳过这[1:]一步?


jfs*_*jfs 7

基于@pts答案的单源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'
Run Code Online (Sandbox Code Playgroud)


Ale*_*lli 6

def tost(i):
  result = []
  while i:
    result.append(chr(i&0xFF))
    i >>= 8
  result.reverse()
  return ''.join(result)
Run Code Online (Sandbox Code Playgroud)

  • tost(0)返回一个空字符串.如果期望的结果为'\ x00',则需要在while循环之前进行i == 0测试 (2认同)