Convert binary string to bytearray in Python 3

寵の児 提交于 2020-01-09 10:25:06

问题


Despite the many related questions, I can't find any that match my problem. I'd like to change a binary string (for example, "0110100001101001") into a byte array (same example, b"hi").

I tried this:

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

but I got:

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

What's the correct way to do this in Python 3?


回答1:


Here's an example of doing it the first way that Patrick mentioned: convert the bitstring to an int and take 8 bits at a time. The natural way to do that generates the bytes in reverse order. To get the bytes back into the proper order I use extended slice notation on the bytearray with a step of -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))

Clearly, Patrick's second way is more compact. :)

However, there's a better way to do this in Python 3: use the int.to_bytes method:

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



回答2:


You have to either convert it to an int and take 8 bits at a time, or chop it into 8 byte long strings and then convert each of them into ints. In Python 3, as PM 2Ring and J.F Sebastian's answers show, the to_bytes() method of int allows you to do the first method very efficiently. This is not available in Python 2, so for people stuck with that, the second method may be more efficient. Here is an example:

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

To break this down, the range statement starts at index 0, and gives us indices into the source string, but advances 8 indices at a time. Since s is 16 characters long, it will give us two indices:

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

(We use list() here to show the values that will be retrieved from the range iterator in Python 3.)

We can then build on this to break the string apart by taking slices of it that are 8 characters long:

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

Then we can convert each of those into integers, base 2:

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

And finally, we wrap the whole thing in bytes() to get the answer:

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



回答3:


>>> zero_one_string = "0110100001101001"
>>> int(zero_one_string, 2).to_bytes((len(zero_one_string) + 7) // 8, 'big')
b'hi'

It returns bytes object that is an immutable sequence of bytes. If you want to get a bytearray -- a mutable sequence of bytes -- then just call bytearray(b'hi').



来源:https://stackoverflow.com/questions/32675679/convert-binary-string-to-bytearray-in-python-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!