将位写入二进制文件

时间:2014-01-19 18:37:05

标签: python python-3.x

我有23位表示为字符串,我需要将此字符串写为4字节的二进制文件。最后一个字节始终为0.以下代码可以工作(Python 3.3),但它感觉不是很优雅(我对Python和编程很新)。你有什么提示让它变得更好吗?似乎for循环可能有用,但如何在循环内进行切片而不会得到IndexError?请注意,当我将这些位提取到一个字节时,我会反转位顺序。

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

4 个答案:

答案 0 :(得分:16)

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

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

答案 1 :(得分:4)

struct模块就是为了这类事情而设计的 - 考虑以下几点:将字节转换分解为一些不必要的中间步骤,以便更清楚地理解它:

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)))

答案 2 :(得分:1)

from array import array

bin_array = array("B")
bits = "10111111111111111011110"

bits = bits + "0" * (32 - len(bits))  # Align bits to 32, i.e. add "0" to tail
for index in range(0, 32, 8):
    byte = bits[index:index + 8][::-1]
    bin_array.append(int(byte, 2))

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

答案 3 :(得分:1)

您可以使用re.findall方法在一行中执行拆分:

>>>bits = "10111111111111111011110"
>>>import re
>>>re.findall(r'\d{1,8}', bits)
['10111111', '11111111', '1011110']

作为算法,您可以将bits填充到长度为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))