2011-06-13 10 views
9

Tengo un problema extraño con el serializador GZip.Problema de compresión de GZipStream (Byte perdido)

Intentando serializar un objeto con datos en él.

siguiente código da resultados (en PUNTO1 de depuración): ms.Length = 100028 y 100027 uncompressedStream.Length =

Después PUNTO1 no es una excepción "Fin de corriente encontró antes de que se completó el análisis", que creo que es el resultado de este byte perdido.

Estoy usando .net 4.0.

 //generating data 
     int length = 100000; 
     byte[] data = new byte[length]; 
     for (int i = 0; i < length; i++) 
     { 
      data[i] = System.Convert.ToByte(i % 100 + i % 50); 
     } 


     //serialization into memory stream 
     IFormatter formatter = new BinaryFormatter(); 
     var ms = new MemoryStream(); 
     formatter.Serialize(ms, data); 
     ms.Seek(0, SeekOrigin.Begin); 

     //GZip zip 
     MemoryStream compressedStream = new MemoryStream(); 
     var Compress = new GZipStream(compressedStream, CompressionMode.Compress); 
     ms.CopyTo(Compress); 
     compressedStream.Seek(0, SeekOrigin.Begin); 

     //GZip Unzip 
     MemoryStream uncompressedStream = new MemoryStream(); 
     var Decompress = new GZipStream(compressedStream, CompressionMode.Decompress); 
     Decompress.CopyTo(uncompressedStream); 
     uncompressedStream.Seek(0, SeekOrigin.Begin); 

     //deserialization from memory stream 
     //POINT1 
     var oo = formatter.Deserialize(uncompressedStream); 
     var o = (byte[])oo; 

     //checking 
     Assert.AreEqual(data.Length, o.Length); 
     for (int i = 0; i < data.Length; i++) 
      Assert.AreEqual(data[i], o[i]); 

Respuesta

14

Las corrientes de compresión no se descargan (y no pueden enjuagarse adecuadamente) hasta que se cierran. Deberá cerrar el GZipStream. Decirle que no cierre la secuencia subyacente (uno de los argumentos constructor) lo hará más fácil.

 //generating data 
     int length = 100000; 
     byte[] data = new byte[length]; 
     for (int i = 0; i < length; i++) 
     { 
      data[i] = System.Convert.ToByte(i % 100 + i % 50); 
     } 

     byte[] o; 
     //serialization into memory stream 
     IFormatter formatter = new BinaryFormatter(); 
     using (var ms = new MemoryStream()) 
     { 
      formatter.Serialize(ms, data); 
      ms.Seek(0, SeekOrigin.Begin); 

      //GZip zip 
      using(MemoryStream compressedStream = new MemoryStream()) 
      { 
       using (var Compress = new GZipStream(compressedStream, CompressionMode.Compress, true)) 
       { 
        ms.CopyTo(Compress); 
       } 
       compressedStream.Seek(0, SeekOrigin.Begin); 
       //GZip Unzip 
       using (MemoryStream uncompressedStream = new MemoryStream()) 
       { 
        using (var Decompress = new GZipStream(compressedStream, CompressionMode.Decompress, true)) 
        { 
         Decompress.CopyTo(uncompressedStream); 
        } 
        uncompressedStream.Seek(0, SeekOrigin.Begin); 
        var oo = formatter.Deserialize(uncompressedStream); 
        o = (byte[])oo; 
       } 
      } 
      //deserialization from memory stream 
      //POINT1 

     } 
     //checking 
     Debug.Assert(data.Length == o.Length); 
     for (int i = 0; i < data.Length; i++) 
      Debug.Assert(data[i] == o[i]); 
+0

Muchas gracias! Funciona como debería ahora. – Yfer

+0

Gracias por esta respuesta. Fui engañado por el artículo de MSDN en GZipStream que imprime la longitud de la corriente comprimida antes de que la transmisión se cierre. Ver http://msdn.microsoft.com/en-us/library/system.io.compression.gzipstream.aspx – Lummo

+0

Has guardado mi trasero. He enviado un comentario a la página de MSDN. –