Pergunta

Estou usando o zlib.net Biblioteca para tentar inflar arquivos que são compactados pelo ZLIB (em uma caixa Linux, talvez). Aqui está o que estou fazendo:

zlib.ZInputStream zinput =
    new zlib.ZInputStream(File.Open(path, FileMode.Open, FileAccess.Read));

while (stopByte != (data = zinput.ReadByte()))
{
  // check data here
}

zinput.Close();

Os bytes de dados correspondem aos bytes de dados compactados, então devo estar fazendo algo errado.

Foi útil?

Solução 2

Parece que cometi o erro de assumir que todos os métodos virtuais foram substituídos, o que não foi o caso. Eu estava usando o zlib.zinputStream.readbyte (), que é apenas o fluxo herdado.readbyte (), que não faz nenhum inflado.

Eu usei o zlib.zinputStream.read () e funcionou como deveria.

Outras dicas

Além de não usar uma instrução "usando" para fechar o fluxo, mesmo diante de uma exceção, isso parece bom para mim. Os dados são definitivamente compactados? Você pode descomprimi -lo com Zlib na caixa Linux?

Tendo olhado para o código -fonte, é bastante horrível - uma chamada para int Read(buffer, offset, length) acabará chamando seu interno int Read() método length tempos, por exemplo. Dado esse tipo de começo instável, não tenho certeza se confiaria no código particularmente pesadamente, mas eu esperava que funcionasse pelo menos um pouco! Você já tentou usar Sharpziplib?

Pulando o cabeçalho Zlib (dois primeiros bytes, 78 9C) e depois usando o DeflateStream embutido em .Net funcionou para mim.

using(var input = File.OpenRead(...))
using(var output = File.Create(...))
{
    // if there are additional headers before the zlib header, you can skip them:
    // input.Seek(xxx, SeekOrigin.Current);

    if (input.ReadByte() != 0x78 || input.ReadByte() != 0x9C)//zlib header
        throw new Exception("Incorrect zlib header");

    using (var deflateStream = new DeflateStream(decryptedData, CompressionMode.Decompress, true))
    {
        deflateStream.CopyTo(output);
    }
}

O código abaixo pode ajudar vocês. Instanciar o objeto e fazer uso das funções.

public class FileCompressionUtility
{
    public FileCompressionUtility()
    {
    }

    public static void CopyStream(System.IO.Stream input, System.IO.Stream output)
    {
        byte[] buffer = new byte[2000];
        int len;
        while ((len = input.Read(buffer, 0, 2000)) > 0)
        {
            output.Write(buffer, 0, len);
        }
        output.Flush();
    }

    public void compressFile(string inFile, string outFile)
    {
        System.IO.FileStream outFileStream = new System.IO.FileStream(outFile, System.IO.FileMode.Create);
        zlib.ZOutputStream outZStream = new zlib.ZOutputStream(outFileStream, zlib.zlibConst.Z_DEFAULT_COMPRESSION);
        System.IO.FileStream inFileStream = new System.IO.FileStream(inFile, System.IO.FileMode.Open);
        try
        {
            CopyStream(inFileStream, outZStream);
        }
        finally
        {
            outZStream.Close();
            outFileStream.Close();
            inFileStream.Close();
        }
    }

    public void uncompressFile(string inFile, string outFile)
    {
        int data = 0;
        int stopByte = -1;
        System.IO.FileStream outFileStream = new System.IO.FileStream(outFile, System.IO.FileMode.Create);
        zlib.ZInputStream inZStream = new zlib.ZInputStream(System.IO.File.Open(inFile, System.IO.FileMode.Open, System.IO.FileAccess.Read));
        while (stopByte != (data = inZStream.Read()))
        {
            byte _dataByte = (byte)data;
            outFileStream.WriteByte(_dataByte);
        }

        inZStream.Close();
        outFileStream.Close();
    }
}

Observe o código de amostra mais de perto, ele está copiando dados de um Filestream regular para o ZoutputStream. A descompressão deve estar acontecendo através dessa camada.

private void decompressFile(string inFile, string outFile)
{
    System.IO.FileStream outFileStream = new System.IO.FileStream(outFile, System.IO.FileMode.Create);
    zlib.ZOutputStream outZStream = new zlib.ZOutputStream(outFileStream);
    System.IO.FileStream inFileStream = new System.IO.FileStream(inFile, System.IO.FileMode.Open);          
    try
    {
        CopyStream(inFileStream, outZStream);
    }
    finally
    {
        outZStream.Close();
        outFileStream.Close();
        inFileStream.Close();
    }
}

Recentemente, tive o infortúnio de servir os documentos anteriormente usando o PHP para uma variedade de navegadores e plataformas, incluindo o IE7. Uma vez eu descobri que os documentos eram zlib'd e não gzip'd (como se pensava na época) que usei Sharpziplib da seguinte maneira no .NET Framework V4 (aproveitando Stream.copyTo):

public static byte[] DecompressZlib(Stream source)
{
    byte[] result = null;
    using (MemoryStream outStream = new MemoryStream())
    {
        using (InflaterInputStream inf = new InflaterInputStream(source))
        {
            inf.CopyTo(outStream);
        }
        result = outStream.ToArray();
    }
    return result;
}

Pensei em colocá -lo aqui, caso alguém precise de ajuda com as aulas para usar do Sharpziplib.

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