如何在System.IO.MemoryStream中使用GZipStream?

我对这个testing函数有一个问题,我在内存string中进行压缩,然后解压缩。 压缩效果很好,但我似乎无法得到解压缩工作。

//Compress System.IO.MemoryStream outStream = new System.IO.MemoryStream(); GZipStream tinyStream = new GZipStream(outStream, CompressionMode.Compress); mStream.Position = 0; mStream.CopyTo(tinyStream); //Decompress outStream.Position = 0; GZipStream bigStream = new GZipStream(outStream, CompressionMode.Decompress); System.IO.MemoryStream bigStreamOut = new System.IO.MemoryStream(); bigStream.CopyTo(bigStreamOut); //Results: //bigStreamOut.Length == 0 //outStream.Position == the end of the stream. 

我相信bigStream out应该至less有数据,特别是如果我的源stream(outStream)正在被读取。 这是一个MSFT错误或我的?

你的代码发生什么事情,你继续打开stream,但你永远不会closures它们。

  • 在第2行中,您创build了一个GZipStream 。 这个stream不会写任何东西到底层的stream,直到它感觉是正确的时候。 你可以通过closures它来告诉它。

  • 但是,如果closures它,它也会closures底层stream( outStream )。 因此你不能使用mStream.Position = 0

您应该始终使用using以确保您的所有stream都closures。 这是你的代码的一个变种工作。

 var inputString = "“ ... ”"; byte[] compressed; string output; using (var outStream = new MemoryStream()) { using (var tinyStream = new GZipStream(outStream, CompressionMode.Compress)) using (var mStream = new MemoryStream(Encoding.UTF8.GetBytes(inputString))) mStream.CopyTo(tinyStream); compressed = outStream.ToArray(); } // “compressed” now contains the compressed string. // Also, all the streams are closed and the above is a self-contained operation. using (var inStream = new MemoryStream(compressed)) using (var bigStream = new GZipStream(inStream, CompressionMode.Decompress)) using (var bigStreamOut = new MemoryStream()) { bigStream.CopyTo(bigStreamOut); output = Encoding.UTF8.GetString(bigStreamOut.ToArray()); } // “output” now contains the uncompressed string. Console.WriteLine(output); 

这是一个已知问题: http : //blogs.msdn.com/b/bclteam/archive/2006/05/10/592551.aspx

我已经改变了你的代码,所以这个工作:

 var mStream = new MemoryStream(new byte[100]); var outStream = new System.IO.MemoryStream(); using (var tinyStream = new GZipStream(outStream, CompressionMode.Compress)) { mStream.CopyTo(tinyStream); } byte[] bb = outStream.ToArray(); //Decompress var bigStream = new GZipStream(new MemoryStream(bb), CompressionMode.Decompress); var bigStreamOut = new System.IO.MemoryStream(); bigStream.CopyTo(bigStreamOut); 

在VB.NET中的另一个实现:

 Imports System.Runtime.CompilerServices Imports System.IO Imports System.IO.Compression Public Module Compressor <Extension()> _ Function CompressASCII(str As String) As Byte() Dim bytes As Byte() = Encoding.ASCII.GetBytes(str) Using ms As New MemoryStream Using gzStream As New GZipStream(ms, CompressionMode.Compress) gzStream.Write(bytes, 0, bytes.Length) End Using Return ms.ToArray End Using End Function <Extension()> _ Function DecompressASCII(compressedString As Byte()) As String Using ms As New MemoryStream(compressedString) Using gzStream As New GZipStream(ms, CompressionMode.Decompress) Using sr As New StreamReader(gzStream, Encoding.ASCII) Return sr.ReadToEnd End Using End Using End Using End Function Sub TestCompression() Dim input As String = "fh3o047gh" Dim compressed As Byte() = input.CompressASCII() Dim decompressed As String = compressed.DecompressASCII() If input <> decompressed Then Throw New ApplicationException("failure!") End If End Sub End Module 
  public static byte[] compress(byte[] data) { using (MemoryStream outStream = new MemoryStream()) { using (GZipStream gzipStream = new GZipStream(outStream, CompressionMode.Compress)) using (MemoryStream srcStream = new MemoryStream(data)) srcStream.CopyTo(gzipStream); return outStream.ToArray(); } } public static byte[] decompress(byte[] compressed) { using (MemoryStream inStream = new MemoryStream(compressed)) using (GZipStream gzipStream = new GZipStream(inStream, CompressionMode.Decompress)) using (MemoryStream outStream = new MemoryStream()) { gzipStream.CopyTo(outStream); return outStream.ToArray(); } } 

如果您正在尝试使用MemoryStream(例如将其传递给另一个函数),但接收到“无法访问封闭的stream”exception。 那么还有另一个GZipStream构造函数可以帮助你。

通过传入true来传递leaveOpen参数,可以指示GZipStream在处理完本身之后将其打开,默认情况下closures目标stream(我没有想到)。 https://msdn.microsoft.com/en-us/library/27ck2z1y(v=vs.110).aspx

 using (FileStream fs = File.OpenRead(f)) using (var compressed = new MemoryStream()) { //Instruct GZipStream to leave the stream open after performing the compression. using (var gzipstream = new GZipStream(compressed, CompressionLevel.Optimal, true)) fs.CopyTo(gzipstream); //Do something with the memorystream compressed.Seek(0, SeekOrigin.Begin); MyFunction(compressed); } 

压缩和解压缩MemoryStream是:

 public static Stream Compress( Stream decompressed, CompressionLevel compressionLevel = CompressionLevel.Fastest) { var compressed = new MemoryStream(); using (var zip = new GZipStream(compressed, compressionLevel, true)) { decompressed.CopyTo(zip); } compressed.Seek(0, SeekOrigin.Begin); return compressed; } public static Stream Decompress(Stream compressed) { var decompressed = new MemoryStream(); using (var zip = new GZipStream(compressed, CompressionMode.Decompress, true)) { zip.CopyTo(decompressed); } decompressed.Seek(0, SeekOrigin.Begin); return decompressed; } 

这将压缩/解压缩的stream打开并在创build之后可用。