将位作为位写入文件

问题描述:

因此,文件系统处理字节,但我正在寻求以位为单位读/写数据到文件。将位作为位写入文件

我有一个大约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沿着每个迭代传递是要写入的二进制文件。这些没有固定的长度,范围从最普通的10到最长的111011001111001100。代码长度为5位,其中的平均值为。上面的代码生成一个大约600mb的文件,仍然离开目标。

目前我正在使用Python 2.7,如果我绝对必须,我可以到Python 3.x。 Python甚至可能吗?像C或C++这样的语言可以更简单吗?

+0

牢记,一个文件必须包含字节的整数(所以你不能真正写一个文件只需2或18位)这不是直接**,而是可以用一些中间缓冲区来完成。 –

+0

那么创建8位缓冲区然后经过一些写入过程?填充最后一个或那个效果? – amza

+0

值是否已经是二进制格式,您可以将它们连接在一起并稍后将它们明确分开?或者你是否需要编码额外的数据来表明边界? –

注意:因为bytes对象只是在Python 2中的str的别名,所以我无法找到(体面的)写下面两种版本的方式,而不使用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`二进制数据的字符串返回一个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()