Python 将位写入二进制文件

Python 将位写入二进制文件,python,python-3.x,Python,Python 3.x,我有23位表示为一个字符串,我需要将这个字符串作为4个字节写入一个二进制文件。最后一个字节总是0。下面的代码可以工作(Python3.3),但感觉不是很优雅(我对Python和编程相当陌生)。你有什么办法让它变得更好吗?for循环似乎很有用,但是如何在循环中进行切片而不使用索引器呢?请注意,当我将位提取到一个字节中时,我会反转位顺序 from array import array bin_array = array("B") bits = "10111111111111111011110"

我有23位表示为一个字符串,我需要将这个字符串作为4个字节写入一个二进制文件。最后一个字节总是0。下面的代码可以工作(Python3.3),但感觉不是很优雅(我对Python和编程相当陌生)。你有什么办法让它变得更好吗?for循环似乎很有用,但是如何在循环中进行切片而不使用索引器呢?请注意,当我将位提取到一个字节中时,我会反转位顺序

from array import array

bin_array = array("B")
bits = "10111111111111111011110"    #Example string. It's always 23 bits
byte1 = bits[:8][::-1]
byte2 = bits[8:16][::-1]
byte3 = bits[16:][::-1]
bin_array.append(int(byte1, 2))
bin_array.append(int(byte2, 2))
bin_array.append(int(byte3, 2))
bin_array.append(0)

with open("test.bnr", "wb") as f:
    f.write(bytes(bin_array))

# Writes [253, 255, 61, 0] to the file

您可以将其视为int,然后按如下方式创建4个字节:

>>> bits = "10111111111111111011110"
>>> int(bits[::-1], 2).to_bytes(4, 'little')
b'\xfd\xff=\x00'

模块是为这样的事情而设计的——考虑下面的内容,其中转换为字节已经被分解成一些不必要的中间步骤以使其更清楚:

import struct

bits = "10111111111111111011110"  # example string. It's always 23 bits
int_value = int(bits[::-1], base=2)
bin_array = struct.pack('i', int_value)
with open("test.bnr", "wb") as f:
    f.write(bin_array)
一种较难阅读但较短的方法是:

bits = "10111111111111111011110"  # example string. It's always 23 bits
with open("test.bnr", "wb") as f:
    f.write(struct.pack('i', int(bits[::-1], 2)))

可以使用以下方法在一行中执行拆分:

作为一种算法,您可以将
位填充到长度32,然后使用
re.findall
方法将其分组为八位:

>>> bits
'10111111111111111011110000000000'
>>> re.findall(r'\d{8}', bits)
['10111111', '11111111', '10111100', '00000000']
您的代码如下所示:

import re
from array import array

bin_array = array("B")
bits = "10111111111111111011110".ljust(32, '0')  # pad it to length 32

for octect in re.findall(r'\d{8}', bits): # split it in 4 octects
    bin_array.append(int(octect[::-1], 2)) # reverse them and append it

with open("test.bnr", "wb") as f:
    f.write(bytes(bin_array))

填充将更加明确,如
bits=“10111111111011110”.ljust(32,'0')
@Jon,即。。。太神了有可能走另一条路吗?类似于:
int.from_bytes(b'\xfd\xff=\x00','little')
和get
“10111111111011110”
@Olav,是的-适当地格式化:
格式(int.from_bytes(b'\xfd\xff=\x00','little'),'023b')[::-1]
这个问题在这个网站上被问了很多次,但这是所有答案中唯一合理的解决方案you@YungGun:直到版本3.2才添加到Python中,因此为了与当前和旧版本的语言兼容,使用
struct
模块(如中所示)可能更可取,因为它将同时在Python 2.x和3.x中工作。@Kebman实际上不是。。。看见
>>> bits
'10111111111111111011110000000000'
>>> re.findall(r'\d{8}', bits)
['10111111', '11111111', '10111100', '00000000']
import re
from array import array

bin_array = array("B")
bits = "10111111111111111011110".ljust(32, '0')  # pad it to length 32

for octect in re.findall(r'\d{8}', bits): # split it in 4 octects
    bin_array.append(int(octect[::-1], 2)) # reverse them and append it

with open("test.bnr", "wb") as f:
    f.write(bytes(bin_array))