【问题标题】:Reading bit by bit for Huffman Compression逐位读取霍夫曼压缩
【发布时间】:2018-03-29 03:22:33
【问题描述】:

我正在编写一个实现霍夫曼压缩的 python 程序。但是,似乎我只能逐字节而​​不是逐位读取/写入 bin 文件。这个问题有什么解决方法吗?由于需要额外的填充,因此不会逐字节处理破坏压缩的目的。此外,如果有人能就这个逐字节问题就霍夫曼压缩的应用向我提供启发,那就太好了。 w

【问题讨论】:

  • 这有点令人困惑,您是想通过逐位读取还是通过修改霍夫曼解码以占用字节来解决这个问题?
  • 我不知道该怎么做,因为霍夫曼编码需要一点一点。然而,计算机程序会逐字节处理内存。
  • 嗯,不一定,有很多技术可以让 Huffman 解码例程处理整个字节(但它们不是树遍历,这可能是您的想法?)
  • 我是 Huffman 的新手,因此任何有关该字节例程的更多信息的链接将不胜感激!

标签: python algorithm compression huffman-code


【解决方案1】:

只需要读取字节的一种潜在方法是直接在解码例程中进行缓冲。这与基于表的解码很好地结合在一起,并且没有进行逐位 IO 的开销(用抽象层隐藏它并不会让它消失,只是将它抹在地毯下)。

在最简单的情况下,基于表的解码需要一个比特流的“窗口”,它与1尽可能大的代码一样大(顺便说一下,这种事情是很大一部分原因为什么许多使用霍夫曼压缩的格式指定的最大代码长度不是超长2),可以通过将缓冲区向右移动直到它具有正确的大小来创建:

window = buffer >> (maxCodeLen - bitsInBuffer)

因为无论如何这都会消除多余的位,所以当缓冲区不够时,可以安全地将 更多 位附加到缓冲区中:

while bitsInBuffer < maxCodeLen:
    buffer = (buffer << 8) | readByte()
    bitsInBuffer += 8

因此字节 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 &lt;&lt; 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 位

【讨论】:

    【解决方案2】:

    分层代码。有一个底层 io 层,它可以一次读取和写入整个文件或缓冲所有文件。在其之上有一层逐位处理霍夫曼码比特流。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      相关资源
      最近更新 更多