在Python 3中将二进制字符串转换为bytearray

2024-04-24 22:18:21 发布

您现在位置:Python中文网/ 问答频道 /正文

尽管有很多相关的问题,我还是找不到与我的问题相符的。我想将二进制字符串(例如,"0110100001101001")更改为字节数组(同样的示例,b"hi")。

我试过这个:

bytes([int(i) for i in "0110100001101001"])

但我得到了:

b'\x00\x01\x01\x00\x01' #... and so on

在Python 3中,正确的方法是什么?


Tags: and字符串in示例for字节bytesso
3条回答

下面是一个例子,按照Patrick提到的第一种方法:将位字符串转换为int,一次取8位。按相反顺序生成字节的自然方法。为了使字节回到正确的顺序,我在bytearray上使用扩展切片表示法,步骤是-1:b[::-1]

def bitstring_to_bytes(s):
    v = int(s, 2)
    b = bytearray()
    while v:
        b.append(v & 0xff)
        v >>= 8
    return bytes(b[::-1])

s = "0110100001101001"
print(bitstring_to_bytes(s))

很明显,帕特里克的第二条路更紧凑。:)

但是,在Python 3中有一个更好的方法:使用int.to_bytes方法:

def bitstring_to_bytes(s):
    return int(s, 2).to_bytes(len(s) // 8, byteorder='big')

你要么把它转换成一个int,一次取8位,要么把它切碎成8字节长的字符串,然后把每个字符串转换成int。在Python 3中,正如PM 2Ring和J.F Sebastian的答案所示,intto_bytes()方法允许您非常高效地执行第一个方法。这在Python2中是不可用的,所以对于坚持使用这种方法的人来说,第二种方法可能更有效。下面是一个例子:

>>> s = "0110100001101001"
>>> bytes(int(s[i : i + 8], 2) for i in range(0, len(s), 8))
b'hi'

为了分解这一点,range语句从索引0开始,将索引放入源字符串中,但一次前进8个索引。由于s有16个字符长,它将为我们提供两个索引:

>>> list(range(0, 50, 8))
[0, 8, 16, 24, 32, 40, 48]
>>> list(range(0, len(s), 8))
[0, 8]

(我们在这里使用list()来显示将从Python 3中的范围迭代器检索的值。)

然后,我们可以在此基础上将字符串分成8个字符:

>>> [s[i : i + 8] for i in range(0, len(s), 8)]
['01101000', '01101001']

然后我们可以把它们转换成整数,基2:

>>> list(int(s[i : i + 8], 2) for i in range(0, len(s), 8))
[104, 105]

最后,我们用bytes()把整个过程包装起来,得到答案:

>>> bytes(int(s[i : i + 8], 2) for i in range(0, len(s), 8))
b'hi'
>>> zero_one_string = "0110100001101001"
>>> int(zero_one_string, 2).to_bytes((len(zero_one_string) + 7) // 8, 'big')
b'hi'

它返回一个不可变字节序列的bytes对象。如果你想得到一个bytearray——一个可变字节序列——那么只要调用bytearray(b'hi')

相关问题 更多 >