3

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;
        }
    }
user1482107
  • 33
  • 1
  • 3
  • You do realise you don't need to nest the usings like that? You can omit the braces after the first two (keeping the third set only), and having all three usings directly below eachother with same indentation. – Rob Levine Jun 26 '12 at 09:31
  • I get the same issue as you - this is very odd - I'll have a closer look. – Rob Levine Jun 26 '12 at 10:16
  • I tried compressing log file to .gz using 7-Zip and it was successfully decompressed by the above method, while archive from posted link was decompressed with only first line, the difference is that one was compressed on UNIX machine (the one from link), and the other one was compressed on Windows machine, if you open it in 7-Zip or view properties using WinRar you'll see that "Host-OS" is "MS-DOS" while in the case of an archive from link it is "UNIX", are the other archives that decompress successfully also from UNIX? – Ivan Golović Jun 26 '12 at 10:35

1 Answers1

4

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);
        }
    }
Karl-Johan Sjögren
  • 16,544
  • 7
  • 59
  • 68
  • Thank you, Iv'e tried SharZipLib, but I'm getting the same result. can you, please, post your function? I might just be missing something. – user1482107 Jun 26 '12 at 12:30
  • Sorry, don't need the function, fixed it. Works like a charm. Thanks. – user1482107 Jun 26 '12 at 12:38
  • No but you are right, a sample is good for others who find this thread so I've added it. – Karl-Johan Sjögren Jun 26 '12 at 13:11
  • Just to clarify, it only works in SharpZipLib version 0.86.0.518. The release notes suggest this version added `Multi-member gzip` support, so perhaps the real issue here is .NET can only read the first member of a multi-member gzip file. – Sam Mar 15 '17 at 23:30
  • See http://stackoverflow.com/questions/15278951/how-to-read-from-file-containing-multiple-gzipstreams/42823057 for more info – Sam Mar 16 '17 at 00:10
  • 2
    I had the exact same issue with a file that I pull from the Google Cloud Storage. Only `SharZipLib` is able to decompress it at the moment. Thanks. – hrzafer Jul 25 '18 at 19:29