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

zlib compress() produces awful compression rate

本文关键字:压缩率 产生了 compress zlib      更新时间:2023-10-16

我想压缩我的数据,使用压缩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;

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

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

我相信

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

这里的关键见解是,zlib 压缩是通过构建霍夫曼树来实现的,霍夫曼树是一种字典类型的数据结构,它指定了简短的"标记",这些"标记"将简洁地表示较长的输入字节序列。 这样,每当这些较长的序列稍后在输入流中重复时,它们都可以被输出流中的等效标记替换,从而大大减少压缩数据的总大小。

但是,该过程的效率在很大程度上取决于构建的霍夫曼树的持久性,这反过来又取决于您的程序在整个压缩过程中保持放气算法的状态。 但是你的代码正在调用 compress(),它意味着一个用于少量数据的单次便利函数,因此 compress() 没有为您的程序提供任何在多次调用它时保留状态的方法。 每次调用 compress(),都会生成一个全新的霍夫曼树,写入用于传递给该调用的其余数据的输出流,然后被遗忘 - 任何后续的 compress() 调用都无法访问它。 这可能是你所看到的效率低下的根源。

解决方法是在需要以多个步骤压缩数据的情况下不使用 compile()。 相反,调用 deflateInit()(为算法分配状态),然后多次调用 deflate()(使用并更新该状态来压缩数据),最后调用 deflateEnd() 进行清理。

使用 deflateInit()deflate()deflateEnd() 而不是 compress() 。 我不知道这是否会改善压缩,因为您没有提供有关数据的信息,只有关于您的程序做什么的最轻微的线索(这些行在循环中吗? 但是,如果您要压缩没有一次加载到内存中的大东西,则不要使用 compress() .