zlib compress()产生可怕的压缩率

时间:2014-11-24 14:47:03

标签: c++ zlib

我想使用compress zlib函数压缩我的数据,因此,代码如下所示:

ifs.read(srcBuf,srcLen) // std::ifstream, srcLen = 256kb
compress(dstBuf, &dstLen, srcBuf, srcLen); // casts are omitted
ofs.write(dstBuf, dstLen); // std::ofstream
dstLen = dstBufSize;

结果文件比原始文件(380mb vs 360mb)小约4%,实际上很糟糕。 同时,Winrar将此文件压缩为70mb文件。我尝试过bzip2和zlib,两者都提供了类似的结果。我想问题是256KB缓冲区太小了,但我想了解它是如何工作的,以及我如何使用zlib来实现更好的压缩。 总的来说,我想制作低级设施将几个文件压缩为1个大文件供内部使用,而compress()看起来非常适合它,但是...

深刻的解释非常欢迎。提前谢谢。

2 个答案:

答案 0 :(得分:2)

我相信你的问题是通过使用compress()函数(而不是deflateInit()/ deflate()/ deflateEnd()),你没有充分利用zlib的压缩能力。

这里的关键见解是zlib压缩是由building up a Huffman tree实现的,{{3}}是一个字典类型的数据结构,它指定简短的“令牌”,它将简洁地表示更长的输入字节序列。这样,只要稍后在输入流中重复那些较长的序列,它们就可以被输出流中的等效标记替换,从而大大减少了压缩数据的总大小。

然而,该过程的效率取决于该组合的霍夫曼树的持久性,而后者依赖于您的程序在压缩过程的整个持续时间内保持deflate算法的状态。但是你的代码正在调用compress(),这对于少量数据来说是一次性的便利函数,因此compress()不会为你的程序提供任何方式来保持多次调用状态。每次调用compress()时,都会生成一个全新的Huffman树,写入输出流,用于传递给该调用的其余数据,然后被遗忘 - 任何后续的compress()调用都将无法访问它。这可能是你所看到的效率低下的根源。

如果您需要在多个步骤中压缩数据,则修复不使用compress()。相反,调用deflateInit()(为算法分配状态),然后多次调用deflate()(使用压缩数据,并更新该状态),最后调用deflateEnd()进行清理。

答案 1 :(得分:1)

使用deflateInit()deflate()deflateEnd()代替compress()。我不知道这是否会改善压缩,因为你没有提供有关数据的信息,只有最简单的线索知道你的程序做了什么(循环中的那些线?)。但是,如果您正在压缩大型内容,而不是一次性加载到内存中,则不要使用compress()