2014-01-19 214 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絕對,謝謝指出! –