Pergunta

System.IO.Compression.GZipStream ou System.IO.Compression.Deflate são compatíveis com compactação zlib?

Foi útil?

Solução

De MSDN sobre System.IO.Compression.GZipStream:

Esta classe representa o formato de dados gzip, que usa um algoritmo padrão da indústria para compactação e descompactação de arquivos sem perdas.

De Perguntas frequentes sobre zlib:

As funções gz* no zlib, por outro lado, usam o formato gzip.

Portanto, zlib e GZipStream devem ser interoperáveis, mas somente se você usar as funções zlib para lidar com o formato gzip.

System.IO.Compression.Deflate e zlib não são interoperáveis.

Se você precisar lidar com arquivos zip (provavelmente não, mas alguém pode precisar disso), você precisará usar SharpZipLib ou outra biblioteca de terceiros.

Outras dicas

DotNetZip inclui um DeflateStream, um ZlibStream e um GZipStream, para lidar com RFC 1950, 1951 e 1952.Todos usam o algoritmo DEFLATE, mas os bytes de enquadramento e cabeçalho são diferentes para cada um.

Como vantagem, os streams no DotNetZip não apresentam o anomalia de expansão do tamanho dos dados sob compactação, relatado nos fluxos integrados.Além disso, não há ZlibStream integrado, enquanto o DotNetZip oferece isso, para uma boa interoperabilidade com o zlib.

Encontrei esse problema com objetos Git.Nesse caso específico, eles armazenam os objetos como blobs deflacionados com um cabeçalho Zlib, que está documentado em RFC 1950.Você pode criar um blob compatível criando um arquivo que contenha:

  • Dois bytes de cabeçalho (CMF e FLG da RFC 1950) com os valores 0x78 0x01
    • CM = 8 = desinflar
    • CINFO = 7 = janela de 32 KB
    • FCHECK = 1 = bits de soma de verificação para este cabeçalho
  • A saída do C# DeflateStream
  • Uma soma de verificação Adler32 dos dados de entrada para o DeflateStream, formato big-endian (MSB primeiro)

Eu fiz minha própria implementação do 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;
        }
    }
}

E basicamente foi isso.

Usei GZipStream para compactar a saída do .NET XmlSerializer e funcionou perfeitamente para descompactar o resultado com gunzip (no cygwin), winzip e outro GZipStream.

Para referência, aqui está o que fiz no 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);
}

Então, para descompactar em 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);
}

O uso do utilitário 'file' no cygwin revela que há de fato uma diferença entre o mesmo arquivo compactado com GZipStream e com GNU GZip (provavelmente informações de cabeçalho como outros declararam neste tópico).Essa diferença, no entanto, parece não importar na prática.

gzip é deflate + alguns dados de cabeçalho/rodapé, como soma de verificação e comprimento, etc.Portanto, eles não são compatíveis no sentido de que um método pode usar um fluxo do outro, mas empregam o mesmo algoritmo de compactação.

Eles apenas compactam os dados usando algoritmos zlib ou deflate, mas não fornecem a saída para algum formato de arquivo específico.Isso significa que se você armazenar o stream como está no disco rígido, provavelmente não conseguirá abri-lo usando algum aplicativo (gzip ou winrar) porque os cabeçalhos dos arquivos (número mágico, etc.) não estão incluídos no stream e você deve escreva-os você mesmo.

A partir do .NET Framework 4.5, o System.IO.Compression.DeflateStream classe usa a biblioteca zlib.

Da aula Artigo MSDN:

Esta classe representa o algoritmo Deflate, que é um algoritmo padrão do setor para compactação e descompactação de arquivos sem perdas.A partir do .NET Framework 4.5, a classe DeflateStream usa a biblioteca zlib.Como resultado, ele fornece um algoritmo de compactação melhor e, na maioria dos casos, um arquivo compactado menor do que o fornecido nas versões anteriores do .NET Framework.

Concordo com o Andrés.Você provavelmente não conseguirá abrir o arquivo em uma ferramenta externa, mas se essa ferramenta esperar um fluxo, você poderá usá-lo.Você também seria capaz de desinflar o arquivo usando a mesma classe de compactação.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top