I'm not familiar with the internals of DeflateStream, but I need to store files in a Vendor's DB system that uses DeflateStream on binary attachments. The first thing I noticed was that all of my files were 10-50% BIGGER after compression, but I attribute that to a less sophisticated compression algo on top of files that are already highly compressed (in this case they were all PDFs). My question however relates to the fact that when I just wrote the original file into the BLOB the Vendor's application had no problem opening it (it opened the attachments I compressed with deflate as well). Is there a header on the compressed data that tells DeflateStream that the data's not compressed and basically pass it on as-is? This is the specification; can anyone familiar with it point where this is defined - or am I off base and the vendor is doing some magic behind the scenes?
3 回答
不,在 DeflateStream 中没有这样的魔力。
内置的 deflateStream 表现出压缩异常,其中先前压缩的数据实际上增加了大小。之前已向 Microsoft 报告过此问题,但他们拒绝解决此问题。它与 DEFLATE 协议的 DeflateStream 中的幼稚实现有关。我知道的避免问题的方法:
使用不会出现此问题的替代 deflateStream。参见 DotNetZip 示例。它包括一个可以正常工作的 DeflateStream。
使用损坏的 DeflateStream,压缩流,比较大小,如果“压缩”流较大,则回退到使用“未压缩”流。
如果你选择前一种情况,你仍然有压缩已经压缩的东西的情况。换句话说,不必要的双重压缩。因此,无论您选择什么,您都可能希望避免这种情况。
流压缩不同于文件压缩。压缩文件时,通常可以对整个文件进行多次传递,并在必须提交之前确定使用哪种压缩方案。压缩流时,通常需要在压缩例程处理足够的数据以了解哪种压缩方法最佳之前开始输出数据。
这种影响可以通过将数据分成块、为每个块决定如何表示数据以及在每个块的开头包含一个标头来标识它是如何存储的来在一定程度上减轻这种影响。不幸的是,额外的块头会增加结果流的大小。此外,许多压缩方案在处理流时提高了效率。如果单独“压缩”,文件中的每 1k 块很可能会扩展,即使压缩整个文件会节省大量空间(因为压缩器可以例如建立公共字节序列的字典)。可以设计一个压缩/解压缩对,以便压缩器逐字写出一个会扩展的数据块(带有一个标头字节表明它是什么),并让解压缩器进程以与压缩器相同的方式阻塞,以便将块以“压缩”形式存储时添加的相同字节序列添加到字典中。这种方法可能是一种很好的方法,尽管它会大大增加解压缩器的复杂性。
不过,我怀疑 DeflateStream 的最大问题是,在不产生与现有“解压缩”代码不兼容的压缩数据的情况下,可能没有任何方法可以提高最坏情况的“压缩”性能。假设有一个字节串 Q,并且需要一个字节序列,当将其馈送到 .net 2.0 附带的“解压缩”代码时,将产生相同的序列。很可能对于 Q 的某些可能值,没有这样的输入序列不会比 Q 大很多。如果是这种情况,微软就无法在没有时间机器的情况下“解决”这个问题。
这完全取决于 DEFLATE 流是如何创建的。
DEFLATE支持“非压缩块”(BTYPE=00),并且该块中的所有数据(如果使用)都将逐字存储,不进行压缩——只有块头、长度和原始数据。但是,流可以是有效的 DEFLATE 流并且包含零个(或不足)“未压缩”块,即使这会导致低于标准的压缩率。
总体压缩率将取决于数据、压缩算法/实现以及执行压缩所付出的努力。
快乐编码。