【问题标题】:Why is deflate making my data BIGGER?为什么放气会使我的数据更大?
【发布时间】:2012-07-14 05:54:28
【问题描述】:

我想压缩一些数据,所以我想我会通过 deflate 来运行流

它从 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();
}

【问题讨论】:

  • 如果将数据放入文件中并压缩会怎样?
  • @GregHewgill zip 给我 465,gz 给我 349,原始是 319。(我不知道我改变了什么,但数据是在每次运行中随机生成的)。我无法告诉 .NET deflate 尝试做什么,因为我将流设为 io 流。我必须编写更多代码来检查此运行中的数据
  • 204 字节小于 1 个网络数据包,也小于 1 个磁盘扇区(在最新的 4k 扇区磁盘上远小于 1 个)。压缩如此少量数据的开销将压倒任何通常不会节省的大小(即使您没有遇到此问题)。
  • @Richard 这是一个快速测试。我的txtbuf会更长。然而,公认的答案完美地解释了事情

标签: .net stream compression deflate


【解决方案1】:

您的数据扩展程度是 DeflateStream 类中的一个错误。该错误也存在于 GZipStream 类中。在这里查看我对这个问题的描述:Why does my C# gzip produce a larger file than Fiddler or PHP?

不要使用 Microsoft 提供的 DeflateStream 类。请改用DotNetZip,它提供替换类。

当您尝试压缩不可压缩的数据时,它会略微膨胀,但只是一小部分。正确编写的 deflate 压缩器的最大扩展是五个字节加上一小部分百分比。 zlib 对不可压缩数据的扩展(原始 deflate 的默认设置)为 5 字节 + 输入大小的 0.03%。您的 304 字节(如果不可压缩)应该从 DeflateStream 等原始 deflate 压缩器中输出为 309 字节。对长度超过 5 或 6 个字节的内容进行 1.9 倍扩展是一个错误。

【讨论】:

    【解决方案2】:

    您尝试压缩的数据可能实际上是不可压缩的(或者您一开始没有很多数据要压缩)。当数据中有重复时,压缩效果最好。

    它可能更大,因为压缩方案正在添加用于解密流的元数据,但由于数据不可压缩或没有很多数据可供压缩生效,它实际上使情况变得更糟。

    如果您执行压缩 zip 文件之类的操作,您会发现解压缩并不总是会使文件变小。

    【讨论】:

    • 肯定会这样,另外,请注意,这取决于流的大小,由于开销的比率,较小的流更难获得压缩带来的好处:数据大小很大更高。
    • 这是一个很好的观点。我想我还应该提到很多数据已经被自然压缩了,比如图像/视频/音频文件,或加密文件。当您尝试压缩这些类型的数据时,情况往往会变得更糟。
    【解决方案3】:

    小数据块通常最终会变大,因为压缩算法使用的代码表会添加到输出中,或者需要更大的样本才能找到足够的样本来处理。

    你没有做错什么。

    【讨论】:

      【解决方案4】:

      不应该

      using (var ms = new DeflateStream(ms2, CompressionMode.Compress, true))
      

      而不是

      using (var ms = new DeflateStream(ms, CompressionMode.Compress, true))
      

      如果你想用 DeflateStream 装饰你的 MemoryStream,它应该是这样的。

      【讨论】:

      • 哎呀,你的权利。这是一个错字。如果我的方式不正确,C# 会出现编译错误
      【解决方案5】:

      您在评论中回答了自己的问题:

      我不知道我改变了什么,但数据是在每次运行时随机生成的

      随机数据难以压缩。通常,当数据中包含许多模式(例如字典或网站中的文本)时,它会很好地压缩。但压缩算法最糟糕的情况是当您面对随机数据时。真正随机的数据中没有任何模式;那么压缩算法如何能够压缩它呢?

      接下来要考虑的是,某些压缩算法在存储数据方面存在开销。它们通常有一些标头位,后跟一些符号数据。对于随机数据,几乎不可能将数据压缩成其他形式,并且最终会在数据之间散布大量的标头位,除了说“以下数据就是这样表示的”之外没有其他用途。

      根据您的压缩格式,开销占总文件大小的百分比可能相对较小或较大。不过,无论哪种情况,您都会产生开销,使您的新文件比旧文件大。

      【讨论】:

      • 不真实,部分原因。我压缩的只有一部分是随机的(时间+一些其他随机的字节),并且有很多 ascii 和 base64 文本应该是可压缩的;)。它实际上是 .NET 实现。糟透了。在 html 文件上使用 deflate 可以得到 26%,而 mono 可以得到原始文件的 5%
      • 不,他没有回答自己的问题。数据没有理由扩展那么多。事实证明这是一个错误,由微软提供。看我的回答。
      【解决方案6】:

      我没有发表评论的声誉,但是压缩性能比您预期的要差的原因不是由于本身的错误,而是显然是专利错误:

      压缩级别不如其他一些应用程序的原因是市场上最有效的压缩算法都受专利保护。另一方面,.net 使用的是非专利的。

      嗯,当我问同样的问题时,我得到的解释(来自 MS 的某个人)是,这与微软无法在不修改 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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-08
        • 1970-01-01
        • 1970-01-01
        • 2010-12-18
        • 1970-01-01
        • 1970-01-01
        • 2015-04-26
        • 2020-02-09
        相关资源
        最近更新 更多