90 lines
2.3 KiB
Python
90 lines
2.3 KiB
Python
class BitWriter(object):
|
|
def __init__(self, f):
|
|
self.accumulator = 0
|
|
self.bcount = 0
|
|
self.out = f
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
self.flush()
|
|
|
|
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 __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
pass
|
|
|
|
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 this module's name from it's file 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:
|
|
with bitio.BitWriter(outfile) as writer:
|
|
chars = '12345abcde'
|
|
for ch in chars:
|
|
writer.writebits(ord(ch), 7)
|
|
|
|
with open('bitio_test.dat', 'rb') as infile:
|
|
with bitio.BitReader(infile) as reader:
|
|
chars = []
|
|
while True:
|
|
x = reader.readbits(7)
|
|
if not reader.read: # End-of-file?
|
|
break
|
|
chars.append(chr(x))
|
|
print(''.join(chars))
|