2012-05-21 39 views
10

Tôi biết cách đọc byte - x.read(number_of_bytes), nhưng làm thế nào tôi có thể đọc bit bằng Python?Làm thế nào để đọc các bit từ một tệp?

tôi phải đọc chỉ có 5 bit (8 bit không [1 byte]) từ một tập tin nhị phân

Bất kỳ ý tưởng hoặc cách tiếp cận?

+1

Là những bit liên tiếp? Nếu vậy, năm bit quan trọng nhất, hoặc năm bit quan trọng nhất trong byte? –

Trả lời

21

Python chỉ có thể đọc một byte tại một thời điểm. Bạn cần đọc một byte đầy đủ, sau đó chỉ cần trích xuất giá trị bạn muốn từ byte đó, ví dụ:

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

Hoặc nếu bạn muốn 5 bit trọng số thấp nhất, chứ không phải là 5 bit quan trọng nhất:

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

Một số hữu ích thông tin thao tác bit khác có thể được tìm thấy ở đây: http://wiki.python.org/moin/BitManipulation

+1

khi danh tiếng của tôi tăng lên 15, tôi sẽ cho bạn ngón tay cái lên! (Tôi mới ở đây) vì vậy, nếu tôi làm điều này: b = x.read (1) firstfivebits = b >> 3 tôi sẽ nhận được 5 bit đầu tiên ... tại sao không firstfivebits = b >> 5? y có nghĩa là ... tại sao b >> 3? –

+7

@HugoMedina nếu bạn không biết tại sao 'firstfivebits = b >> 3' bạn chắc chắn bạn nên fiddlin 'với bit? (Bạn có thể bị mù hoặc một cái gì đó;). –

+1

bây giờ tôi nhận được nó, vì 1 byte = 8 bit, chúng tôi sẽ áp dụng toán tử shift 3 (giống như xóa 3 bit quan trọng nhất) vì vậy chúng ta sẽ nhận được 5 bit còn lại trong byte –

2

Như trạng thái trả lời được chấp nhận, I/O Python chuẩn chỉ có thể đọc và ghi toàn bộ byte (s) tại một thời điểm. Tuy nhiên, bạn có thể mô phỏng một luồng bit như vậy bằng cách sử dụng công thức này cho Bitwise I/O.

Cập nhật:

Kể từ khi trang web của Rosetta Mã của GNU license cho phép sao chép đúng nguyên văn, đây là phiên bản Python của bit-stream I/O trong toàn bộ:

Cập nhật 2:

Sau khi sửa đổi phiên bản Python của Mã Rosetta để làm việc không thay đổi trong cả hai Python 2 & 3, tôi đã kết hợp các thay đổi vào câu trả lời này.

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

Ví dụ sử dụng khác cho thấy cách "bẻ" luồng ASCII 8 bit loại bỏ bit "không sử dụng" quan trọng nhất ... và đọc lại.

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) 

... và "decrunch" dòng giống nhau:

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)) 
Các vấn đề liên quan