2012-05-21 20 views
10

私はバイトを読み取る方法を知っています - x.read(number_of_bytes)、しかし私はどのようにビットをPythonで読むことができますか?ファイルからビットを読み取る方法は?

Iバイナリファイル

任意のアイデアやアプローチからわずか5ビット(しない8ビットを[1つのバイト])を読み込む必要がありますか?

+1

は、これらのビットは連続していますか?もしそうなら、バイトの5つの最上位ビット、または5つの最下位ビット、 –

答えて

21

Pythonは、一度に1バイトだけを読み取ることができます。 1バイトで読み込み、そのバイトから必要な値を抽出するだけです(例:

b = x.read(1) 
firstfivebits = b >> 3 

それとも、5つの最下位ビットではなく、5つの最上位ビットたい場合:他のいくつかの便利なビット操作情報はここで見つけることができます

b = x.read(1) 
lastfivebits = b & 0b11111 

:としてhttp://wiki.python.org/moin/BitManipulation

+1

私の評判が15になると、私はあなたに親指をあげよう! (私はここにいる) これを行うと: b = x.read(1) firstfivebits = b >> 3 私は最初の5ビットを取得します...なぜfirstfivebits = b >> 5? yは...なぜb >> 3? –

+7

@HugoMedinaなぜ 'firstfivebits = b >> 3'あなたが確かにあなたはビットでフィドリンでなければならないのか分からないのですか? (あなたは盲目になるかもしれないし、何かに行くかもしれない)。 –

+1

今私は1バイト= 8ビットで、右シフト演算子3を適用するので(3つの最下位ビットを削除するように)、残りの5ビットをバイト –

2

を標準のPython I/Oは、一度に1バイトずつしか読み書きできません。しかし、Bitwise I/Oのこのレシピを使用して、このようなビットストリームをシミュレートできます。

更新:

ロゼッタコードウェブサイトのGNU licenseは、逐語的にコピーすることができますので、ここにその全体がビットストリームI/OのPythonのバージョンです:

アップデート2:

は、 Rosetta CodeのPythonバージョンをPython 2 & 3で変更しないで変更した後、この回答に変更を加えました。

class BitWriter(object): 
    def __init__(self, f): 
     self.accumulator = 0 
     self.bcount = 0 
     self.out = f 

    def __del__(self): 
     try: 
      self.flush() 
     except ValueError: # I/O operation on closed file 
      pass 

    def _writebit(self, bit): 
     if self.bcount == 8: 
      self.flush() 
     if bit > 0: 
      self.accumulator |= 1 << 7-self.bcount 
     self.bcount += 1 

    def writebits(self, bits, n): 
     while n > 0: 
      self._writebit(bits & 1 << n-1) 
      n -= 1 

    def flush(self): 
     self.out.write(bytearray([self.accumulator])) 
     self.accumulator = 0 
     self.bcount = 0 


class BitReader(object): 
    def __init__(self, f): 
     self.input = f 
     self.accumulator = 0 
     self.bcount = 0 
     self.read = 0 

    def _readbit(self): 
     if not self.bcount: 
      a = self.input.read(1) 
      if a: 
       self.accumulator = ord(a) 
      self.bcount = 8 
      self.read = len(a) 
     rv = (self.accumulator & (1 << self.bcount-1)) >> self.bcount-1 
     self.bcount -= 1 
     return rv 

    def readbits(self, n): 
     v = 0 
     while n > 0: 
      v = (v << 1) | self._readbit() 
      n -= 1 
     return v 

if __name__ == '__main__': 
    import os 
    import sys 
    # determine module name from this file's name and import it 
    module_name = os.path.splitext(os.path.basename(__file__))[0] 
    bitio = __import__(module_name) 

    with open('bitio_test.dat', 'wb') as outfile: 
     writer = bitio.BitWriter(outfile) 
     chars = '12345abcde' 
     for ch in chars: 
      writer.writebits(ord(ch), 7) 

    with open('bitio_test.dat', 'rb') as infile: 
     reader = bitio.BitReader(infile) 
     chars = [] 
     while True: 
      x = reader.readbits(7) 
      if reader.read == 0: 
       break 
      chars.append(chr(x)) 
     print(''.join(chars)) 

8ビットのバイトストリームのASCIIストリームを使用して、最も重要な「未使用」ビットを破棄する方法を示すもう1つの使用例を示します。

import sys 
import bitio 

o = bitio.BitWriter(sys.stdout) 
c = sys.stdin.read(1) 
while len(c) > 0: 
    o.writebits(ord(c), 7) 
    c = sys.stdin.read(1) 

...と "decrunch" と同じストリーム:

import sys 
import bitio 

r = bitio.BitReader(sys.stdin) 
while True: 
    x = r.readbits(7) 
    if not r.read: # nothing read 
     break 
    sys.stdout.write(chr(x)) 
関連する問題