Decompressing using GZipStream returns only the fi

2019-02-18 18:33发布

问题:

I’ve been working on a function parsing 3rd party fms logs. The logs are in Gzip, so I use a decompressing function that works for any other Gzip files we use.

When decompressing these files I only get the first line of the compressed file, there’s no exception, it just doesn’t find the rest of the bytes as if there's an EOF at the first line. I tried using Ionic.Zlib instead of System.IO.Compression but the result was the same. The files don’t seem to be corrupted in any way, decompressing them with Winrar works.

If anybody has any idea of how to solve this, I’ll appreciate your help. Thanks

You can download a sample file here: http://www.adjustyourset.tv/fms_6F9E_20120621_0001.log.gz

This is my decompression function:

    public static bool DecompressGZip(String fileRoot, String destRoot)
    {
        try
        {
            using (FileStream fileStram = new FileStream(fileRoot, FileMode.Open, FileAccess.Read))
            {
                using (FileStream fOutStream = new FileStream(destRoot, FileMode.Create, FileAccess.Write))
                {
                    using (GZipStream zipStream = new GZipStream(fileStram, CompressionMode.Decompress, true))
                    {
                        byte[] buffer = new byte[4096];
                        int numRead;

                        while ((numRead = zipStream.Read(buffer, 0, buffer.Length)) != 0)
                        {
                            fOutStream.Write(buffer, 0, numRead);
                        }
                        return true;
                    }
                }

            }
        }
        catch (Exception ex)
        {
            LogUtils.SaveToLog(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), "Eror decompressing " + fileRoot + " : " + ex.Message, Constants.systemLog, 209715200, 6);
            return false;
        }
    }

回答1:

I've put the last 45 minutes wrapping my head around this problem but I just can't explain why it isn't working. Somehow the DeflateStream-class isn't decoding your data properly. I wrote up my own GZip-parser (I can share the code if anyone wants to check it) which reads all the headers and checks them for validity (to make sure that there are no funny stuff there) and then use DeflateStream to inflate the actual data but with your file it still just gets me the first line.

If I recompress using your logfile using GZipStream (after first decompressing it with winrar) then it is decompressed just fine again both my my own parser and your own sample.

There seems to be some critizism on the net about Microsofts implementation of Deflate (http://www.virtualdub.org/blog/pivot/entry.php?id=335) so it might be that you found one of it's quirks.

However, a simple solution to your problem is to switch to SharZipLib (http://www.icsharpcode.net/opensource/sharpziplib/), I tried it out and it can decompress your file just fine.

    public static void DecompressGZip(String fileRoot, String destRoot)
    {
        using (FileStream fileStram = new FileStream(fileRoot, FileMode.Open, FileAccess.Read))
        using (GZipInputStream zipStream = new GZipInputStream(fileStram))
        using (StreamReader sr = new StreamReader(zipStream))
        {
            string data = sr.ReadToEnd();
            File.WriteAllText(destRoot, data);
        }
    }