【问题标题】:Huffman compression compressed file is bigger than original file霍夫曼压缩压缩文件比原始文件大
【发布时间】:2019-10-16 23:01:52
【问题描述】:

我已经使用优先级队列在 Java 中实现了 Huffman 编码算法,其中我将树从根遍历到叶,并根据符号在输入中出现的次数将编码示例设为 #=000011。一切都很好,树的构建很好,编码正如预期的那样:但是我得到的输出文件比原始文件大。我目前在遍历树的左节点和右节点时将“0”和“1”附加到字符串。这是我使用 OutputStream 写入的 write 方法:

private void writeToFile(Map<Byte, BitSet> dictCode, byte[] data, OutputStream os) throws IOException {
    for (int i = 0; i < data.length; i++) {
        os.write(dictCode.get(data[i]).toByteArray());
    }
 }

data 是我的文件(我将压缩的文件),以字节为单位

Map&lt;Byte, BitSet&gt; dictCodeBitSet 是该字节的霍夫曼树代码路径

例如,10 的 Bitset 将为 10={3},因为只有第三位为真:000100

我是用字节写的,为什么我的新文件比原来的大?

【问题讨论】:

  • 这可能发生在数据不可压缩的情况下,例如,如果它已经被压缩了,因为您必须在字典本身中添加。
  • 但是我正在用文本文件进行测试,我认为不正常;不是吗?
  • 没有文字,没有。您的输出是否使用不同的实现正确解压缩?
  • 我还没有实现解压
  • 对不起,我误会了。不,我没有尝试其他实现

标签: java compression huffman-code


【解决方案1】:

您的问题似乎是您正在写出 字节流 而不是 位流

假设在您的代码中,dictCode 映射对于 data 中的每个字节都有一个重要的条目,那么:

private void writeToFile(Map<Byte, BitSet> dictCode, byte[] data, OutputStream os) throws IOException {
    for (int i = 0; i < data.length; i++) {
        os.write(dictCode.get(data[i]).toByteArray());
    }
 }
对于 data 中的每个字节,

正在向 os 写入至少一个字节。因此,如果数据是输入文件中的原始字节,则永远不能使用此代码编写较小的文件。

例如使用 令牌流

111 010 000 1101 111

你在写

00000111 00000010 00000000 00001101 00000111

而不是

11101000 01101111 

这就是您没有看到任何压缩的原因。

【讨论】:

  • 谢谢,这个问题有什么简单的解决办法吗?
  • 我认为 Java 不支持开箱即用的比特流,因此您可能需要进行一些修改来构建您想要输出的字节。
  • 哦,我需要移位吗?
  • 是的,类似的东西。可能有一些关于如何将位写入字节的示例。
  • 感谢您的大力帮助。欣赏!