将位作为位写入文件

时间:2016-05-13 19:01:16

标签: python binaryfiles

因此文件系统处理字节,但我希望以位的形式读取/写入数据文件。

我有一个约850mb的文件,目标是使其低于100mb。我使用delta + huffman编码生成一个"代码表"二进制。当你添加所有"位" (又名文件中的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 ++这样的语言可以更容易吗?

1 个答案:

答案 0 :(得分:2)

注意:因为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()