Pregunta

¿Son System.IO.Compression.GZipStream o System.IO.Compression.Deflate compatibles con la compresión zlib?

¿Fue útil?

Solución

De MSDN acerca de System.IO.Compression.GZipStream:

Esta clase representa el formato de datos gzip, que utiliza un algoritmo estándar de la industria para la compresión y descompresión de archivos sin pérdidas.

Desde el Preguntas frecuentes sobre zlib:

Por otro lado, las funciones gz* en zlib utilizan el formato gzip.

Por lo tanto, zlib y GZipStream deberían ser interoperables, pero solo si usa las funciones zlib para manejar el formato gzip.

Según se informa, System.IO.Compression.Deflate y zlib no son interoperables.

Si necesita manejar archivos zip (probablemente no los necesite, pero alguien más podría necesitarlos), debe usar SharpZipLib u otra biblioteca de terceros.

Otros consejos

DotNetZip incluye DeflateStream, ZlibStream y GZipStream, para manejar RFC 1950, 1951 y 1952.Todos usan el algoritmo DEFLATE pero los bytes de encuadre y encabezado son diferentes para cada uno.

Como ventaja, las transmisiones en DotNetZip no presentan la anomalía de la expansión del tamaño de los datos bajo compresión, informado contra las corrientes integradas.Además, no hay ZlibStream integrado, mientras que DotNetZip sí lo ofrece, para una buena interoperabilidad con zlib.

Me encontré con este problema con los objetos de Git.En ese caso particular, almacenan los objetos como blobs desinflados con un encabezado Zlib, que está documentado en RFC 1950.Puede crear un blob compatible creando un archivo que contenga:

  • Dos bytes de encabezado (CMF y FLG de RFC 1950) con los valores 0x78 0x01
    • CM = 8 = desinflar
    • CINFO = 7 = ventana de 32Kb
    • FCHECK = 1 = bits de suma de comprobación para este encabezado
  • La salida de C# DeflateStream
  • Una suma de comprobación Adler32 de los datos de entrada al DeflateStream, formato big-endian (primero MSB)

Hice mi propia implementación de Adler

public class Adler32Computer
{
    private int a = 1;
    private int b = 0;

    public int Checksum
    {
        get
        {
            return ((b * 65536) + a);
        }
    }

    private static readonly int Modulus = 65521;

    public void Update(byte[] data, int offset, int length)
    {
        for (int counter = 0; counter < length; ++counter)
        {
            a = (a + (data[offset + counter])) % Modulus;
            b = (b + a) % Modulus;
        }
    }
}

Y eso fue prácticamente todo.

He usado GZipStream para comprimir la salida de .NET XmlSerializer y funcionó perfectamente bien para descomprimir el resultado con gunzip (en cygwin), winzip y otro GZipStream.

Como referencia, esto es lo que hice en código:

FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
using (GZipStream gzStream = new GZipStream(fs, CompressionMode.Compress))
{
  XmlSerializer serializer = new XmlSerializer(typeof(MyDataType));
  serializer.Serialize(gzStream, myData);
}

Luego, para descomprimir en c#

FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
using (Stream input = new GZipStream(fs, CompressionMode.Decompress))
{
   XmlSerializer serializer = new XmlSerializer(typeof(MyDataType));
   myData = (MyDataType) serializer.Deserialize(input);
}

El uso de la utilidad 'archivo' en cygwin revela que, de hecho, existe una diferencia entre el mismo archivo comprimido con GZipStream y con GNU GZip (probablemente información del encabezado como otros han indicado en este hilo).Sin embargo, esta diferencia parece no importar en la práctica.

gzip está desinflado + algunos datos de encabezado/pie de página, como suma de verificación y longitud, etc.Por lo tanto, no son compatibles en el sentido de que un método puede usar una secuencia del otro, pero emplean el mismo algoritmo de compresión.

Simplemente comprimen los datos usando algoritmos zlib o deflate, pero no proporcionan el resultado para algún formato de archivo específico.Esto significa que si almacena la transmisión tal como está en el disco duro, lo más probable es que no pueda abrirla usando alguna aplicación (gzip o winrar) porque los encabezados de los archivos (número mágico, etc.) no están incluidos en la transmisión y debería hacerlo. escríbalos usted mismo.

A partir de .NET Framework 4.5, System.IO.Compression.DeflateStream La clase usa la biblioteca zlib.

De la clase artículo de MSDN:

Esta clase representa el algoritmo Deflate, que es un algoritmo estándar de la industria para la compresión y descompresión de archivos sin pérdidas.A partir de .NET Framework 4.5, la clase DeflateStream utiliza la biblioteca zlib.Como resultado, proporciona un mejor algoritmo de compresión y, en la mayoría de los casos, un archivo comprimido más pequeño que el que proporcionaba en versiones anteriores de .NET Framework.

Estoy de acuerdo con andres.Probablemente no podrá abrir el archivo en una herramienta externa, pero si esa herramienta espera una transmisión, es posible que pueda utilizarla.También podrá desinflar el archivo usando la misma clase de compresión.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top