2012-05-15 33 views
16

Estoy tratando de comprimir y descomprimir un Stream usando Compression.DeflateStream. La compresión parece funcionar correctamente, ya que el siguiente código comprime mi Stream a una matriz de 110 bytes de longitud. Sin embargo, leer los resultados de Stream descomprimidos es una cadena vacía.Comprimir y descomprimir un Stream con 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; 
    } 
} 

¿Alguien me puede ayudar en esto? Muchas gracias.

Respuesta

25

arreglar su función Compress: flujo

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

comprimido no se lavó antes de devolver la matriz de bytes resultante.

+0

Esto funciona. Muchas gracias – greijner

+3

Debe decir que si llama 'Flush' en lugar de' Close' no funciona. Pensé que 'Close' llamar' Flush' internamente era la razón por la que funciona, pero no. –

+4

@Luke: de [la documentación para 'DeflateStream.Flush()'] (https://msdn.microsoft.com/en-us/library/system.io.compression.deflatestream.flush (v = vs.110) .aspx): _ "La implementación actual de este método no vacía el búfer interno. El búfer interno se vacía cuando se elimina el objeto." _ En cuanto a por qué este es el diseño, 'Stream.Flush()' está destinado a descargue el búfer interno, pero una secuencia desinflada no se puede finalizar hasta que sepa que está en el _end_, que solo es posible cuando la secuencia está cerrada. –

9

intente cerrar las corrientes:

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

Estoy usando las mismas funciones de descompresión de compresión. Descomprimir funciona bien pero el objeto Stream devuelto me da. No se puede acceder a un Stream cerrado. mensaje mientras intento trabajar en ello. el mismo código estaba funcionando antes de comprimir las funciones de descompresión. ¿alguna idea? – afr0

4

Todas esas respuestas están muy lejos de la forma ideal porque todos ustedes olvidaron que "usar" la eliminación y el cierre de sus medios corrientes que no es necesaria una estrecha adicional(). Creo que el código ideal sería el siguiente:

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