将位作为位写入文件
Writing bits as bits to a file
所以文件系统处理字节,但我正在寻找 read/write 数据以位为单位的文件。
我有一个大约 850 MB 的文件,我的目标是让它小于 100 MB。我使用 delta + huffman 编码生成了一个 "code table" 的二进制文件。当您添加所有 "bits"(即文件中 0 和 1 的总数)时,您将得到大约 781,000,000 "bits",所以理论上我应该能够将它们存储在大约 90mb 左右。这就是我 运行 遇到问题的地方。
根据我在 SO 周围看到的其他答案,这是我得到的最接近的答案:
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
是要写入的二进制文件。它们没有固定的长度,范围从最常见的 10
到最长的 111011001111001100
。 平均码长为5位。上面的代码生成了一个大约 600mb 的文件,离目标还差得很远。
目前我正在使用 Python 2.7,如果绝对需要,我可以达到 Python 3.x。在 Python 中甚至可能吗?像 C 或 C++ 这样的语言会更容易吗?
注意:因为 bytes
对象只是 python 中 str
的别名 2 我无法找到(体面的)编写以下内容的方式两个版本都没有使用 if USING_VS_3
.
作为从一串位到可以写入文件的字节的最小接口,您可以使用如下内容:
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:]
因此,给出像 '111011001111001100' to
bits_to_bytes` 这样的二进制数据字符串将 return 一个包含(写入文件的字节数据)和(剩余位)的 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()
所以文件系统处理字节,但我正在寻找 read/write 数据以位为单位的文件。
我有一个大约 850 MB 的文件,我的目标是让它小于 100 MB。我使用 delta + huffman 编码生成了一个 "code table" 的二进制文件。当您添加所有 "bits"(即文件中 0 和 1 的总数)时,您将得到大约 781,000,000 "bits",所以理论上我应该能够将它们存储在大约 90mb 左右。这就是我 运行 遇到问题的地方。
根据我在 SO 周围看到的其他答案,这是我得到的最接近的答案:
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
是要写入的二进制文件。它们没有固定的长度,范围从最常见的 10
到最长的 111011001111001100
。 平均码长为5位。上面的代码生成了一个大约 600mb 的文件,离目标还差得很远。
目前我正在使用 Python 2.7,如果绝对需要,我可以达到 Python 3.x。在 Python 中甚至可能吗?像 C 或 C++ 这样的语言会更容易吗?
注意:因为 bytes
对象只是 python 中 str
的别名 2 我无法找到(体面的)编写以下内容的方式两个版本都没有使用 if USING_VS_3
.
作为从一串位到可以写入文件的字节的最小接口,您可以使用如下内容:
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:]
因此,给出像 '111011001111001100' to
bits_to_bytes` 这样的二进制数据字符串将 return 一个包含(写入文件的字节数据)和(剩余位)的 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()