处理MemoryStreams和GZipStreams

时间:2017-01-18 16:28:23

标签: c# idisposable gzipstream

我想在序列化时压缩ProtoBuffer对象并在反序列化时解压缩。不幸的是,C#stdlib只提供了对流而不是byte []的压缩例程,这使得它比函数调用更加冗长。我的代码到目前为止:

class MyObject{
 public string P1 {get; set;}
 public string P2 {get; set;}
 // ...

 public byte[] Serialize(){
   var builder = new BinaryFormat.MyObject.Builder();
   builder.SetP1(P1);
   builder.SetP2(P2);
   // ...

   // object is now build, let's compress it.
   var ms = new MemoryStream();
   // Without this using, the serialisatoin/deserialisation Tests fail
   using (var gz = new GZipStream(ms, CompressionMode.Compress))
   {
     builder.Build().WriteTo(gz);
   }
   return ms.ToArray();
 }

 public void Deserialize(byte[] data)
 {
   var ms = new MemoryStream();
   // Here, Tests work, even when the "using" is left out, like this:
   (new GZipStream(new MemoryStream(data), CompressionMode.Decompress)).CopyTo(ms);
   var msg = BinaryFormat.MachineInfo.ParseFrom(ms.ToArray());

   P1 = msg.P1;
   P2 = msg.P2;
   // ...
 }
}

处理流时,似乎必须手动处理对象。我想知道为什么会这样,我希望GZipStream是完全托管的代码。我想知道如果Deserialize只是偶然起作用,我是否应该处理MemoryStreams。

我知道我可以通过简单地使用第三方压缩库来解决这个问题,但除了这个问题之外,这还有点。

1 个答案:

答案 0 :(得分:1)

需要处理

GZipStream,因此它将其缓冲区的最终压缩块从其缓冲区刷新到其底层流,它还会在传入的流上调用dispose,除非您使用了重载{{ 3}}

如果您使用未处理MemoryStream的重载,那么放置MemoryStream并不重要,因为它没有在任何地方写入其内部缓冲区。它唯一能做的就是设置一些标志并将Task对象设置为null,这样如果流的生命周期长于处置点,它就可以更快地进行GC。

    protected override void Dispose(bool disposing)
    {
        try {
            if (disposing) {
                _isOpen = false;
                _writable = false;
                _expandable = false;
                // Don't set buffer to null - allow TryGetBuffer, GetBuffer & ToArray to work.
#if FEATURE_ASYNC_IO
                _lastReadTask = null;
#endif
            }
        }
        finally {
            // Call base.Close() to cleanup async IO resources
            base.Dispose(disposing);
        }
    }

此外,虽然评论说&#34;调用base.Close()来清理异步IO资源&#34; <{1}}类的base dispose函数什么都不做。

Stream

所有这一切,在解压缩GZipStream时,你可能会因为没有处理MemoryStream而放弃它,因为解压缩它不会在任何地方缓冲字节,所以不需要刷新任何缓冲区。 / p>