2014-01-19 248 views
5

我有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 

回答

14

你可以把它当作一个int,然后再创建4个字节如下:

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

+1我喜欢这个。太糟糕了Python2.7没有这个功能 –

+0

@Jon那真是太神奇了。走另一条路可行吗?例如:'int.from_bytes(b'\ xfd \ xff = \ x00','little')'并获得'“10111111111111111011110”' – Olav

+1

@Olav,yup - 适当格式化:'format(int.from_bytes(b' \ xfd \ xff = \ x00','little'),'023b')[:: - 1]' –

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

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

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

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

作为一个算法,可以垫bits到长度32然后用re.findall方法组它octects:

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

填充将会更加明确,因为“bits =”10111111111111111011110“.ljust(32,'0')' –

+0

@JonClements绝对,谢谢指出! –