在 Python 3 中将二进制字符串转换为 bytearray
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32675679/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert binary string to bytearray in Python 3
提问by Numeri says Reinstate Monica
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"
).
尽管有许多相关的问题,但我找不到与我的问题相符的问题。我想将二进制字符串(例如"0110100001101001"
)更改为字节数组(相同的示例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?
在 Python 3 中执行此操作的正确方法是什么?
采纳答案by PM 2Ring
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]
.
这是按照 Patrick 提到的第一种方式进行操作的示例:将位串转换为 int 并一次取 8 位。这样做的自然方法是以相反的顺序生成字节。为了将字节恢复到正确的顺序,我在字节数组上使用了扩展切片符号,步长为 -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. :)
显然,Patrick 的第二种方式更加紧凑。:)
However, there's a better way to do this in Python 3: use the int.to_bytesmethod:
但是,在 Python 3 中有更好的方法来做到这一点:使用int.to_bytes方法:
def bitstring_to_bytes(s):
return int(s, 2).to_bytes(len(s) // 8, byteorder='big')
回答by Patrick Maupin
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:
您必须将其转换为 int 并一次取 8 位,或者将其切成 8 字节长的字符串,然后将它们中的每一个都转换为 int。在 Python 3 中,正如 PM 2Ring 和 JF Sebastian 的回答所示,to_bytes()
方法int
允许您非常有效地执行第一种方法。这在 Python 2 中不可用,因此对于坚持使用它的人来说,第二种方法可能更有效。下面是一个例子:
>>> 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:
为了分解这个,范围语句从索引 0 开始,并为我们提供源字符串的索引,但一次推进 8 个索引。由于s
长度为 16 个字符,它将为我们提供两个索引:
>>> 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.)
(我们list()
在这里使用来显示将从 Python 3 中的范围迭代器中检索的值。)
We can then build on this to break the string apart by taking slices of it that are 8 characters long:
然后我们可以在此基础上通过取 8 个字符长的切片来拆分字符串:
>>> [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:
然后我们可以将它们中的每一个转换为整数,基数为 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()
以获得答案:
>>> bytes(int(s[i : i + 8], 2) for i in range(0, len(s), 8))
b'hi'
回答by jfs
>>> 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')
.
它返回bytes
一个不可变字节序列的对象。如果你想得到一个bytearray
——一个可变的字节序列——那么只需调用bytearray(b'hi')
.