2012-12-18 104 views
2

我有一個包含一系列比特的文本文件,在ASCII:蟒字面二進制進制轉換

cat myFile.txt 
0101111011100011001... 

我想寫這對以二進制模式的其它文件,這樣我可以讀取它一位君主。我怎麼能達到?我試過已經用代碼轉換它:

f2=open(fileOut, 'wb') 
    with open(fileIn) as f: 
     while True: 
      c = f.read(1) 
      byte = byte+str(c) 
      if not c: 
       print "End of file" 
       break 
      if count % 8 is 0: 
       count = 0 
       print hex(int(byte,2)) 
       try: 
        f2.write('\\x'+hex(int(byte,2))[2:]).zfill(2) 
       except: 
        pass 
       byte = '' 
      count += 1 

但這並沒有達到我計劃要做的。你有什麼提示嗎?

回答

1

使用struct

import struct 
... 
f2.write(struct.pack('b', int(byte,2))) # signed 8 bit int 

​​
+0

謝謝你很多_ :-) – user1225343

2
  • 閱讀並一次寫一個字節是痛苦的緩慢。你可能會圍繞〜45倍加速你的代碼只需通過讀取每次調用該文件的更多數據,以f.readf.write

    |------------------+--------------------| 
    | using_loop_20480 | 8.34 msec per loop | 
    | using_loop_8  | 354 msec per loop | 
    |------------------+--------------------| 
    

    using_loop在這個崗位的底部顯示的代碼。 using_loop_20480是chunksize = 1024 * 20的代碼。這意味着每次從該文件讀取20480個字節。 using_loop_1與chunksize = 1的代碼相同。

  • 關於count % 8 is 0:請勿使用is來比較數值;改爲使用==。下面是一些例子,爲什麼is可能會給你錯誤的結果(也許不是在您發佈的代碼,但在一般情況下,is是不恰當的位置):

    In [5]: 1L is 1 
    Out[5]: False 
    
    In [6]: 1L == 1 
    Out[6]: True 
    
    In [7]: 0.0 is 0 
    Out[7]: False 
    
    In [8]: 0.0 == 0 
    Out[8]: True 
    
  • 而不是

    struct.pack('{n}B'.format(n = len(bytes)), *bytes) 
    

    你可以使用

    bytearray(bytes) 
    

    不僅打字少,而且速度也稍微快一點。

    |------------------------------+--------------------| 
    |    using_loop_20480 | 8.34 msec per loop | 
    | using_loop_with_struct_20480 | 8.59 msec per loop | 
    |------------------------------+--------------------| 
    

    bytearrays是這項工作的良好匹配,因爲它填補了關於數據作爲字符串和 數字的序列之間的 差距。

    In [16]: bytearray([97,98,99]) 
    Out[16]: bytearray(b'abc') 
    
    In [17]: print(bytearray([97,98,99])) 
    abc 
    

    正如你可以看到上面,bytearray(bytes)允許你 通過使其整數的一個序列(在 range(256))定義字節組,並允許其寫出,就好像是一個 字符串:g.write(bytearray(bytes))


def using_loop(output, chunksize): 
    with open(filename, 'r') as f, open(output, 'wb') as g: 
     while True: 
      chunk = f.read(chunksize) 
      if chunk == '': 
       break 
      bytes = [int(chunk[i:i+8], 2) 
        for i in range(0, len(chunk), 8)] 
      g.write(bytearray(bytes)) 

確保CHUNKSIZE是8的倍數。


這是我用來創建表的代碼。需要注意的是prettytable也做類似這樣的東西,它可能是最好使用自己的代碼,而不是我砍:table.py

這是我來時使用的代碼模塊:utils_timeit.py。 (它使用table.py)。

這裏是我用的時間using_loop(和其他變種)的代碼:timeit_bytearray_vs_struct.py

+0

我喜歡你的表,什麼是你的時間設置? – Kos

+1

@Kos:我編輯了我的帖子,並使用了我使用的代碼的主要鏈接。我很抱歉,這是很多代碼,並沒有真正準備好發佈。 – unutbu

+0

謝謝! ([2]和[3]指的是相同的鏈接,可能是一個錯字)。我有點希望'timeit'有這個內置的地方;-)你的黑客似乎自動檢測列的寬度,我不是當然,如果'prettytable'也能做到這一點。我有點記得尋找它,並最終自己寫,但我不記得是否是關於'texttable'或'prettytable'包。 – Kos