【问题标题】:using gZipStream with one or two memory streams makes a big difference将 gZipStream 与一个或两个内存流一起使用会产生很大的不同
【发布时间】:2012-08-23 12:16:42
【问题描述】:

我肯定遗漏了一些非常明显的东西,但谁能解释为什么在第二种情况下压缩率要好得多?!

案例 1:非常低的压缩率,有时甚至会增长。

using (var memoryStream = new System.IO.MemoryStream())
using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress))
{
  new BinaryFormatter().Serialize(gZipStream, obj);
  gZipStream.Close();
  return memoryStream.ToArray();
}

案例 2:更好的压缩,我没有得到尺寸增长。

using (MemoryStream msCompressed = new MemoryStream())
using (GZipStream gZipStream = new GZipStream(msCompressed, CompressionMode.Compress))
using (MemoryStream msDecompressed = new MemoryStream())
{
  new BinaryFormatter().Serialize(msDecompressed, obj);
  byte[] byteArray = msDecompressed.ToArray();

  gZipStream.Write(byteArray, 0, byteArray.Length);
  gZipStream.Close();
  return msCompressed.ToArray();
}

我已经完成了镜像解压,在这两种情况下我都可以将其反序列化为源对象而没有任何问题。

以下是一些统计数据:

UncSize:58062085B,Comp1:46828139B,0.81%

UncSize:58062085B,Comp2:31326029B,0.54%

UncSize:7624735B,Comp1:7743947B,1.02%

UncSize:7624735B,Comp2:5337522B,0.70%

UncSize:1237628B,Comp1:1265406B,1.02%

UncSize:1237628B,Comp2:921695B,0.74%

【问题讨论】:

    标签: c# compression memorystream gzipstream binaryformatter


    【解决方案1】:

    您没有说您使用的是哪个版本的 .NET。在 4.0 之前的版本中,GZipStream 在每次写入的基础上压缩数据。也就是说,它会压缩您发送给它的缓冲区。在您的第一个示例中,Serialize 方法可能会将非常小的缓冲区写入流(一次一个字段)。在您的第二个示例中,Serialize 将整个对象序列化到内存流,然后将内存流的缓冲区写入一大块 GZipStream。当GZipStream 有更大的缓冲区(64K 接近最佳值)可供使用时,它的表现要好得多。

    在 .NET 4.0 中可能仍然是这种情况。我不记得我是否测试过。

    我过去处理这个问题的方式是使用BufferedStream

    using (var mstream = new MemoryStream())
    {
        using (var bstream = new BufferedStream(new GZipStream(mstream, CompressionMode.Compress), 65536))
        {
            new BinaryFormatter().Serialize(btream, obj);
        }
        return mstream.ToArray();
    }
    

    这样,压缩器可以使用 64K 缓冲区。

    在 .NET 4.0 之前,为GZipStream 提供大于 64K 的缓冲区没有任何好处。我看到一些信息表明 .NET 4.0 中的压缩器可以更好地使用更大的缓冲区进行压缩。但是,我自己没有测试过。

    【讨论】:

    • 谢谢。这正是我一直在寻找的。我正在使用 .net 4.0,但情况仍然如此。正如您所说,64k 效果最好。较小的缓冲区会导致较弱的压缩。我已将代码更改为使用 BufferStream 而不是两个内存流来进行更好的内存管理。谢谢
    猜你喜欢
    • 2015-12-29
    • 2013-01-31
    • 2015-05-14
    • 2011-04-12
    • 1970-01-01
    • 2014-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多