Zlib最小放气尺寸

时间:2015-06-18 19:04:55

标签: c zlib

我试图找出是否有办法根据输入缓冲区的大小计算输出缓冲区所需的最小大小。

这个问题类似于zlib, deflate: How much memory to allocate?,但不一样。我是在孤立地询问每个块,而不是整个流。

假设我们有两个缓冲区:INPUTOUTPUT,我们有一个BUFFER_SIZE,即4096字节。 (只是一个方便的数字,没有特别的原因我选择这个尺寸。)

如果我放气使用:

deflate(stream, Z_PARTIAL_FLUSH)

这样每个块都被压缩,并立即刷新到输出缓冲区,有没有办法可以保证输出缓冲区中有足够的存储空间而不需要重新分配?

从表面上看,我们假设DEFLATED数据总是比未压缩的输入数据更大(假设我们使用的压缩级别大于0。)

当然,情况并非总是如此 - 特别是对于小值。例如,如果我们收缩单个字节,由于LZW流中的头文件和字典之类的开销,收缩的数据显然会大于未压缩的数据。

考虑LZW如何工作,看起来如果我们的输入数据至少是256个字节(意味着最坏的情况,每个字节都不同,我们无法真正压缩任何东西),我们应该意识到输入大小为LESS超过256个字节+ zlib头可能需要一个LARGER输出缓冲区。

但是,通常情况下,真实世界的应用程序不会像这样压缩小尺寸。因此,假设输入/输出缓冲区更像4K,是否有某种方法可以保证输出压缩数据比输入数据更小?

(另外,我知道deflateBound,但由于开销,宁可避免使用它。)

或者,换句话说,是否有一些最小缓冲区大小我可以用于输入/输出缓冲区,这将保证输出数据(压缩流)将小于输入数据?或者总是有一些病态情况会导致输出流大于输入流,无论大小如何?

2 个答案:

答案 0 :(得分:2)

虽然我无法解决您的问题,但我可以单独评论部分问题。

  

是否有一些保证输出压缩数据的方法   比输入数据更小?

绝对不是。压缩输出总是可能比某些输入大。否则你将无法压缩其他输入。

  

(另外,我知道deflateBound,但宁愿避免它因为   开销。)

开销?真的吗?对于合理的尺寸,我们说的是比输入缓冲区大一小百分之一。

顺便说一下,deflateBound()提供整个输出流大小的界限,作为整个输入流大小的函数。当您处于输入不完整且输出空间不足的deflate()次调用中时,它无法帮助您。例如,您可能仍然在下一次deflate()调用中对输出挂起并传递,而不提供任何新输入。然后,隔离呼叫的扩展比率是无限的。

  

由于LZW中的标题和词典之类的开销   流。

放气不是LZW。它使用的方法称为LZ77。它与LZW非常不同,LZW现在已经过时了。没有"字典"存储在压缩的deflate数据中。 "字典"只是在当前正在压缩或解压缩的数据之前的未压缩数据。

  

或者,换句话说,我有一些最小的缓冲区大小   可用于输入/输出缓冲区......

zlib接口背后的整个想法是让您不必担心缓冲区中的内容。您只需继续为deflate()inflate()调用更多输入数据和更多输出空间,直到您完成为止,一切顺利。如果您需要进行多次调用以使用一个输入缓冲区,或者多次调用以填充一个输出缓冲区,则无关紧要。您只需要循环来进行更多调用,在需要时提供更多输入,并在需要时配置输出并提供新的输出空间。

答案 1 :(得分:1)

信息理论要求必须始终存在“压缩”到更大的病态的病例。

This page以zlib的最坏情况编码大小开始 - 看起来最坏的情况是增长为6个字节,加上每个启动的16KB块5个字节。因此,如果你总是在小于16KB的情况下进行刷新,那么拥有11个字节的缓冲区加上你的刷新间隔应该是安全的。

除非您能够严格控制正在压缩的数据类型,否则查找病态案例并不难。任何随机数生成器都会很快找到你。