2012-05-15 6 views
16

Próbuję skompresować i rozpakować strumień przy użyciu Compression.DeflateStream. Kompresowanie wydaje się działać poprawnie, ponieważ poniższy kod kompresuje moją Stream do tablicy o długości 110 bajtów. Jednak odczyt strumienia dekompresji spowoduje pusty ciąg znaków.Kompresja i dekompresja strumienia z kompresją.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; 
    } 
} 

Czy ktoś może mi pomóc w tej sprawie? Wielkie dzięki.

Odpowiedz

25

Poprawianie Compress funkcję:

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

skompresowany strumień nie przedostaną przed powrotem powstały układ bajtów.

+0

To działa. Wielkie dzięki – greijner

+3

Musisz wywołać, że jeśli nazwiesz "Flush" zamiast "Close", to nie działa. Myślałem, że 'Close' nazywając' Flush' wewnętrznie, to dlaczego to działa, ale nie. –

+4

@Luke: od [dokumentacji dla 'DeflateStream.Flush()'] (https://msdn.microsoft.com/en-us/library/system.io.compression.deflatestream.flush (v = vs.110) .aspx): _ "Obecna implementacja tej metody nie powoduje opróżnienia bufora wewnętrznego, bufor wewnętrzny jest przepłukiwany, gdy obiekt jest usuwany." _ Dlaczego jest to projekt, 'Stream.Flush()' ma na celu przepłucz wewnętrzne buforowanie, ale strumień deflacji nie może zostać sfinalizowany, dopóki nie będzie wiedział, że jesteś na pozycji _end_, co jest możliwe tylko wtedy, gdy strumień jest zamknięty. –

9

Spróbuj zamknąć strumienie:

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

Używam tych samych funkcji dekompresji kompresji. Dekompresja działa dobrze, ale zwrócony obiekt Stream daje mi. Nie można uzyskać dostępu do zamkniętego strumienia. wiadomość, podczas gdy próbuję nad nią pracować. ten sam kod działał przed funkcjami dekompresowania kompresji. dowolny pomysł? – afr0

4

Wszystkie te odpowiedzi są daleko od idealnej formie, bo wy wszyscy zapomnieli, że „za pomocą” utylizacji i zamykanie strumieni swoje środki, że dodatkowe Close() nie jest potrzebne. Myślę, że idealny kod będzie taki:

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; 
    } 
}