2016-05-13 17 views
2

ファイルシステムはバイトを扱うが、私はビット単位でファイルにデータを読み書きするつもりだ。ビットをファイルに書き込む

私は〜850MBのファイルを持っていますが、目標は100MB未満にすることです。私はバイナリの "コードテーブル"を生成するために、delta + huffmanエンコーディングを使用しました。すべての "ビット"(別名ファイルの0と1の合計数)を追加すると、約781,000,000の "ビット"が得られるので、理論的にはこれらを約90MB程度で保存できるはずです。これが私が問題にぶつかるところです。書き込まれるバイナリがある

with open(r'encoded_file.bin', 'wb') as f: 
    for val in filedict: 
      int_val = int(val[::-1], base=2) 
      bin_array = struct.pack('i', int_value) 
      f.write(bin_array) 

valは各反復に沿って渡されている:私が見た他の回答に基づいて

は周りのSO、これは私が得ている最も近いです。これらは固定長ではなく、10から最も一般的なものは111011001111001100までです。 平均コードは5ビットです。上記のコードは約600MBのファイルを生成しますが、ターゲットからまだ離れています。

現在、私はPython 2.7を使用しています。私が絶対に必要ならPython 3.xにアクセスできます。 Pythonでも可能ですか? CやC++のような言語で簡単にできますか?

+0

ファイルはバイトの全体数を(含まれている必要がありますので、あなたがいない実際にことを念頭に置いて保管ファイルにちょうど2または18ビットを書き込む)これは**直接可能ではありませんが、いくつかの中間バッファで実現できます。 –

+0

8ビットのバッファを作成してから書き込みプロセスを実行しますか?最後のものか何かをその効果に詰めている間に? – amza

+0

値をバイナリ形式にしていますが、それらを連結して後で明確に区別することはできますか?または、境界を示すために余分なデータをエンコードする必要がありますか? –

答えて

2

注:bytesオブジェクトはstrのエイリアスであり、if USING_VS_3を使用せずに両方のバージョンで機能する以下のコードを書くことはできませんでした。だから、'111011001111001100' to bits_to_bytes`意志のようなバイナリデータの文字列を与える

def _gen_parts(bits): 
    for start in range(0,len(bits),8): 
     b = int(bits[start:start+8], base=2) 
     if USING_VS_3: 
      yield b #bytes takes an iterator of ints 
     else: 
      yield chr(b) 

def bits_to_bytes(bits): # -> (bytes, "leftover") 
    split_i = -(len(bits)%8) 
    byte_gen = _gen_parts(bits[:split_i]) 
    if USING_VS_3: 
     whole = bytes(byte_gen) 
    else: 
     whole = "".join(byte_gen) 
    return whole, bits[split_i:] 

:あなたはこのようなものを使用することができ、ファイルに書き込むことができるバイトにビット列から行くには、最小限のインターフェイスとして

(ファイルに書き込むためのバイトデータ)と(残りのビット)の2つの項目タプルを返します。

次に部分バイトバッファを処理するためのシンプルかつ最適化されていないファイルのインターフェイスは、このようなことができます:

class Bit_writer: 
    def __init__(self,file): 
     self.file = file 
     self.buffer = "" 

    def write(self,bits): 
     byte_data, self.buffer = bits_to_bytes(self.buffer + bits) 
     self.file.write(byte_data) 

    def close(self): 
     #you may want to handle the padding differently? 
     byte_data,_ = bits_to_bytes("{0.buffer:0<8}".format(self)) 
     self.file.write(byte_data) 
     self.file.close() 

    def __enter__(self): # This will let you use a 'with' block 
     return self 
    def __exit__(self,*unused): 
     self.file.close() 
関連する問題