2012-05-15 6 views
16

Ich versuche, einen Stream unter Verwendung Compression.DeflateStream zu komprimieren und dekomprimieren. Das Komprimieren scheint korrekt zu funktionieren, da der folgende Code meinen Stream auf ein 110 Bytes langes Array komprimiert. Das Lesen des dekomprimierten Streams führt jedoch zu einer leeren Zeichenfolge.Komprimieren und dekomprimieren Sie einen Stream mit Compression.DeflateStream

class Program 
{ 
    static void Main(string[] args) 
    { 
     // Compress a random string value 
     string value = Path.GetRandomFileName(); 
     byte[] compressedBytes; 

     using (var writer = new StreamWriter(new MemoryStream())) 
     { 
      writer.Write(value); 
      writer.Flush(); 
      writer.BaseStream.Position = 0; 

      compressedBytes = Compress(writer.BaseStream); 
     } 

     // Decompress compressed bytes 
     Stream decompressedStream = Decompress(compressedBytes); 
     // here already applies: decompressedStream.Length == 0 

     using (var reader = new StreamReader(decompressedStream)) 
     { 
      string decompressedValue = reader.ReadToEnd(); 

      if (value == decompressedValue) 
       Console.WriteLine("Success"); 
      else 
       Console.WriteLine("Failed"); 
     } 
    } 

    private static byte[] Compress(Stream input) 
    { 
     using (var compressStream = new MemoryStream()) 
     using (var compressor = new DeflateStream(compressStream, CompressionMode.Compress)) 
     { 
      input.CopyTo(compressor); 
      return compressStream.ToArray(); 
     } 
    } 

    private static Stream Decompress(byte[] input) 
    { 
     var output = new MemoryStream(); 

     using (var compressStream = new MemoryStream(input)) 
     using (var decompressor = new DeflateStream(compressStream, CompressionMode.Decompress)) 
      decompressor.CopyTo(output); 

     output.Position = 0; 
     return output; 
    } 
} 

Kann mir jemand dabei helfen? Vielen Dank.

Antwort

25

Fix Ihre Compress Funktion:

private static byte[] Compress(Stream input) 
{ 
    using(var compressStream = new MemoryStream()) 
    using(var compressor = new DeflateStream(compressStream, CompressionMode.Compress)) 
    { 
     input.CopyTo(compressor); 
     compressor.Close(); 
     return compressStream.ToArray(); 
    } 
} 

komprimierten Strom nicht vor der Rückkehr in das resultierende Byte-Array gespült wurde.

+0

Dies funktioniert. Vielen Dank – greijner

+3

Muss rufen Sie, dass wenn Sie 'Flush' statt' Close' aufrufen, es nicht funktioniert. Ich dachte, 'Close' nennt' Flush' intern, warum das funktioniert, aber nein. –

+4

@Luke: aus [die Dokumentation für 'DeflateStream.Flush()'] (https://msdn.microsoft.com/en-us/library/system.io.compression.deflatestream.flush (v = vs.110) .aspx): _ "Die aktuelle Implementierung dieser Methode löscht den internen Puffer nicht. Der interne Puffer wird geleert, wenn das Objekt entfernt wird." _ Warum dies der Entwurf ist, ist "Stream.Flush()" beabsichtigt Flush internes Buffering, aber ein Deflate-Stream kann nicht finalisiert werden, bis er weiß, dass Sie sich am _end_ befinden, was nur möglich ist, wenn der Stream _closed_ ist. –

9

Versuchen Sie, die Ströme endet:

class Program 
{ 
    static void Main(string[] args) 
    { 
     // Compress a random string value 
     string value = DateTime.Now.ToLongTimeString(); 
     byte[] compressedBytes; 

     using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(value))) 
     { 
      compressedBytes = Compress(stream); 
     } 


     // Decompress compressed bytes 
     using (var decompressedStream = Decompress(compressedBytes)) 
     using (var reader = new StreamReader(decompressedStream)) 
     { 
      string decompressedValue = reader.ReadToEnd(); 

      if (value == decompressedValue) 
       Console.WriteLine("Success"); 
      else 
       Console.WriteLine("Failed"); 
     } 
    } 

    public static byte[] Compress(Stream input) 
    { 
     using (var compressedStream = new MemoryStream()) 
     using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress)) 
     { 
      input.CopyTo(zipStream); 
      zipStream.Close(); 
      return compressedStream.ToArray(); 
     } 
    } 

    public static Stream Decompress(byte[] data) 
    { 
     var output = new MemoryStream(); 
     using(var compressedStream = new MemoryStream(data)) 
     using(var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress)) 
     { 
      zipStream.CopyTo(output); 
      zipStream.Close(); 
      output.Position = 0; 
      return output; 
     } 
    } 
} 
+1

Ich benutze die gleichen komprimieren Dekomprimierungsfunktionen. Decompress funktioniert gut, aber das zurückgegebene Stream-Objekt gibt mir. Es kann nicht auf einen geschlossenen Stream zugegriffen werden. Nachricht, während ich versuche, daran zu arbeiten. Derselbe Code funktionierte vor dem Komprimieren von dekomprimierten Funktionen. irgendeine Idee? – afr0

4

All diese Antworten von der idealen Form weit entfernt sind, weil alle von Ihnen vergessen, dass „mit“ Entsorgung und Schließen Ströme seine Mittel, die zusätzliche Close() ist nicht erforderlich. Ich denke, dass idealer Code so sein wird:

public static class CompressionHelper 
{ 
    public static byte[] Compress(byte[] data) 
    { 
     byte[] compressArray = null; 
     try 
     { 
      using (MemoryStream memoryStream = new MemoryStream()) 
      { 
       using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress)) 
       { 
        deflateStream.Write(data, 0, data.Length); 
       } 
       compressArray = memoryStream.ToArray(); 
      } 
     } 
     catch (Exception exception) 
     { 
      // do something ! 
     } 
     return compressArray; 
    } 

    public static byte[] Decompress(byte[] data) 
    { 
     byte[] decompressedArray = null; 
     try 
     { 
      using (MemoryStream decompressedStream = new MemoryStream()) 
      { 
       using (MemoryStream compressStream = new MemoryStream(data)) 
       { 
        using (DeflateStream deflateStream = new DeflateStream(compressStream, CompressionMode.Decompress)) 
        { 
         deflateStream.CopyTo(decompressedStream); 
        } 
       } 
       decompressedArray = decompressedStream.ToArray(); 
      } 
     } 
     catch (Exception exception) 
     { 
      // do something ! 
     } 

     return decompressedArray; 
    } 
} 
Verwandte Themen