我想压缩一些数据,所以我想通过放气来运行流
它从304字节增加到578字节。这是1.9倍大。我试着压缩它。。。。。我在这里做错了什么?
using (MemoryStream ms2 = new MemoryStream())
using (var ms = new DeflateStream(ms2, CompressionMode.Compress, true))
{
ms.WriteByte(1);
ms.WriteShort((short)txtbuf.Length);
ms.Write(txtbuf, 0, txtbuf.Length);
ms.WriteShort((short)buf2.Length);
ms.Write(buf2, 0, buf2.Length);
ms.WriteShort((short)buf3.Length);
ms.Write(buf3, 0, buf3.Length);
ms.Flush();
result_buf = ms2.ToArray();
}
数据扩展的程度是DeflateStream类中的错误。该bug也存在于GZipStream类中。请参阅我对这个问题的描述:为什么我的C#gzip生成的文件比Fiddler或PHP大?。
不要使用Microsoft提供的DeflateStream类。请改用DotNetZip,它提供了替换类。
当你试图压缩不可压缩的数据时,它会稍微膨胀,但只会膨胀一小部分。正确写入的deflate压缩器的最大扩展是五个字节加上百分之一的一小部分。zlib对不可压缩数据的扩展(使用原始deflate的默认设置)为5字节+0.03%的输入大小。如果304字节是不可压缩的,应该从像DeflateStream这样的原始deflate压缩器中得到309字节。长度超过五六个字节的东西的1.9倍扩展是一个错误。
您试图压缩的数据可能实际上是不可压缩的(或者您一开始没有很多数据要压缩)。当数据中存在重复时,压缩效果最佳。
它可能更大,因为压缩方案添加了用于解密流的元数据,但由于数据不可压缩,或者没有太多数据可供压缩生效,这实际上使情况变得更糟。
如果你做了一些类似于压缩zip文件的事情,你会发现解压缩并不总是让事情变得更小。
小块数据通常会变大,因为压缩算法使用添加到输出中的代码表,或者需要更大的样本才能找到足够的数据。
你没有做错什么。
不应该是吗
using (var ms = new DeflateStream(ms2, CompressionMode.Compress, true))
而不是
using (var ms = new DeflateStream(ms, CompressionMode.Compress, true))
如果你想用DeflateStream来装饰你的MemoryStream,它应该是这样的。
您在评论中回答了自己的问题:
我不知道我更改了什么,但每次运行时数据都是随机生成的
随机数据很难压缩。一般来说,当数据中有很多模式(比如字典或网站上的文本)时,它会压缩得很好。但对于压缩算法来说,更糟糕的情况是当你面对随机数据时。真正的随机数据中没有任何模式;那么,压缩算法如何能够对其进行压缩呢?
接下来要考虑的是,某些压缩算法在存储数据方面存在开销。它们通常有一些标头位,后面跟着一些符号数据。对于随机数据,几乎不可能将数据压缩成其他形式,最终你会在数据之间穿插大量的头位,这些头位除了说"下面的数据就是这样表示的"之外没有其他用途
根据您的压缩格式,开销占文件总大小的百分比可能相对较小,也可能较大。然而,在任何一种情况下,都会有使新文件比旧文件大的开销。
我没有留下评论的名声,但是压缩性能比你预期的要差的原因是不是本身的错误,而是一个专利错误:
压缩级别不如其他一些应用程序的原因是,市场上最有效的压缩算法都受到专利保护。net则使用了一个非专利的。
和
当我问同样的问题时,我(从微软的某个人那里)得到的解释是,这与微软不能在不修改GZip算法的情况下使用它有关;由于专利/许可问题。
http://social.msdn.microsoft.com/Forums/fr-FR/c5f0b53c-a2d5-4407-b43b-9da8d39c01df/why-do-gzipstream-compression-ratio-so-bad?forum=netfxbcl
最初我怀疑微软的gzip实现;我知道他们实现了Deflate算法,这不是最有效的,但没有专利。
http://challenge-me.ws/post/2010/11/05/Do-Not-Take-Microsofts-Code-for-Granted.aspx