我正在编写一个实现Huffman压缩的python程序。但是,似乎我只能逐字节而不是逐位读取/写入bin文件。这个问题有解决方法吗?不会逐字节处理会破坏压缩的目的,因为需要额外的填充。另外,如果有人能够了解有关这种逐字节问题的霍夫曼压缩的应用,那就太棒了。瓦特
答案 0 :(得分:2)
只需要读取字节的潜在方法是直接在解码例程中缓冲。这与基于表的解码很好地结合,并且没有任何逐行IO的开销(隐藏抽象层不会使它消失,只是在地毯下擦除它。)
在最简单的情况下,基于表的解码需要比特流的“窗口”,这个窗口与 1 一样大,是最大可能的代码(顺便提一下,这类事情是很大一部分原因为什么许多使用Huffman压缩的格式指定的最大代码长度不是超长 2 ),这可以通过将缓冲区向右移动直到它具有正确的大小来创建:
window = buffer >> (maxCodeLen - bitsInBuffer)
因为无论如何都可以去除多余的比特,所以当没有足够的比例时,可以安全地将更多位附加到缓冲区的绝对必要位置:
while bitsInBuffer < maxCodeLen:
buffer = (buffer << 8) | readByte()
bitsInBuffer += 8
因此byte-IO就足够了。实际上,如果你愿意,你可以读取稍大一些的块(例如当时两个字节)。顺便说一句,这里有一个小问题:如果文件的所有字节都已被读取并且缓冲区中没有足够的位(这是有效比特流可能发生的合法条件),您只需填写“填充” “(基本上在没有ORing的情况下向左移位)。
解码本身可能如下所示:
# this line does the actual decoding
(symbol, length) = table[window]
# remove that code from the buffer
bitsInBuffer -= length
buffer = buffer & ((1 << bitsInBuffer) - 1)
# use decoded symbol
这很容易,困难的部分是构建table
。一种方法(不是一种很好的方式,但是一种简单的方法)是从0到包括(1 << maxCodeLen) - 1
的每个整数,并使用逐位树行走方式解码其中的第一个符号你已经习惯了。更快捷的方法是获取每个符号/代码对并使用它来填充表格的正确条目:
# for each symbol/code do this:
bottomSize = maxCodeLen - codeLen
topBits = code << bottomSize
for bottom in range(0, (1 << bottomSize) - 1):
table[topBits | bottom] = (symbol, codeLen)
顺便说一下,这些代码都没有经过测试,只是大致展示了它是如何完成的。它还采用了一种特殊的方法将比特流打包成字节,第一位在字节的顶部。
1:某些多阶段解码策略能够使用较小的窗口,如果代码长度没有限制,则可能需要这样做。
2:例如,Deflate
最多15位答案 1 :(得分:0)
分层代码。有一个底层io层,可以一次性完成所有文件的读取和写入,也可以使用缓冲。在上面有一个层,用于按比特处理霍夫曼码比特流。