Unzipping a Stream in C#

13,171

Solution 1

I am using SharpZipLib and it's working great !

Below is a function that encapsulate the library

 public static void Compress(FileInfo sourceFile, string destinationFileName,string destinationTempFileName)
        {
            Crc32 crc = new Crc32();
            string zipFile = Path.Combine(sourceFile.Directory.FullName, destinationTempFileName);
            zipFile = Path.ChangeExtension(zipFile, ZIP_EXTENSION);

            using (FileStream fs = File.Create(zipFile))
            {
                using (ZipOutputStream zOut = new ZipOutputStream(fs))
                {
                    zOut.SetLevel(9);
                    ZipEntry entry = new ZipEntry(ZipEntry.CleanName(destinationFileName));

                    entry.DateTime = DateTime.Now;
                    entry.ZipFileIndex = 1;
                    entry.Size = sourceFile.Length;

                    using (FileStream sourceStream = sourceFile.OpenRead())
                    {
                        crc.Reset();
                        long len = sourceFile.Length;
                        byte[] buffer = new byte[bufferSize];
                        while (len > 0)
                        {
                            int readSoFar = sourceStream.Read(buffer, 0, buffer.Length);
                            crc.Update(buffer, 0, readSoFar);
                            len -= readSoFar;
                        }
                        entry.Crc = crc.Value;
                        zOut.PutNextEntry(entry);

                        len = sourceStream.Length;
                        sourceStream.Seek(0, SeekOrigin.Begin);
                        while (len > 0)
                        {
                            int readSoFar = sourceStream.Read(buffer, 0, buffer.Length);
                            zOut.Write(buffer, 0, readSoFar);
                            len -= readSoFar;
                        }
                    }
                    zOut.Finish();
                    zOut.Close();
                }
                fs.Close();
            }
        }

Solution 2

Apparently SharpZipLib is now unmaintained and you probably want to avoid it: https://stackoverflow.com/a/593030

In .NET 4.5 there is now built in support for zip files, so for your example it would be:

var data = new WebClient().DownloadData(downloadUrl);

//Create the stream
var stream = new MemoryStream(data);

var document = new XmlDocument();

//zip
var zipArchive = new ZipArchive(stream);

//Load report straight from the zip stream
document.Load(zipArchive.Entries[0].Open());

Solution 3

If you have a byte array that contains a zip archive with a single file, you can use the ZipArchive class to get an unzipped byte array with the file's data. ZipArchive is contained in .NET 4.5, in the assembly System.IO.Compression.FileSystem (you need to reference it explicitly).

The following function, adapted from this answer, works for me:

public static byte[] UnzipSingleEntry(byte[] zipped)
{
    using (var memoryStream = new MemoryStream(zipped))
    {
        using (var archive = new ZipArchive(memoryStream))
        {
            foreach (ZipArchiveEntry entry in archive.Entries)
            {
                using (var entryStream = entry.Open())
                {
                    using (var reader = new BinaryReader(entryStream))
                    {
                        return reader.ReadBytes((int)entry.Length);
                    }
                }
            }
        }
    }
    return null; // To quiet my compiler
}

Solution 4

As the others have mentioned GZip and Zip are not the same so you might need to use a zip library. I use a library called: DotNetZip - available from the below site:

http://dotnetzip.codeplex.com/

Solution 5

From GZipStream Class description:

Compressed GZipStream objects written to a file with an extension of .gz can be decompressed using many common compression tools; however, this class does not inherently provide functionality for adding files to or extracting files from .zip archives

So unless you control server-side files, I'd suggest looking for specific zip-targeted library (SharpZipLib for example).

Share:
13,171
Roee Gavirel
Author by

Roee Gavirel

Updated on June 15, 2022

Comments

  • Roee Gavirel
    Roee Gavirel almost 2 years

    I'm working in C#, and I'm downloading for the internet a zip file with one XML file in it. and I wish to load this XML file. This is what I have so far:

    byte[] data;
    WebClient webClient = new WebClient();
    try {
        data = webClient.DownloadData(downloadUrl);
    }
    catch (Exception ex) {
        Console.WriteLine("Error in DownloadData (Ex:{0})", ex.Message);
        throw;
    }
    
    if (data == null) {
        Console.WriteLine("Bulk data is null");
        throw new Exception("Bulk data is null");
    }
    
    //Create the stream
    MemoryStream stream = new MemoryStream(data);
    XmlDocument document = new XmlDocument();
    
    //Gzip
    GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress);
    
    //Load report straight from the gzip stream
    try {
        document.Load(gzipStream);
    }
    catch (Exception ex) {
        Console.WriteLine("Error in Load (Ex:{0})", ex.Message);
        throw;
    }
    

    in document.Load I'm always getting the following exception:
    The magic number in GZip header is not correct. Make sure you are passing in a GZip stream.

    What I'm doing wrong?

  • Michael
    Michael over 5 years
    If you want support for other compression formats not supported like tgz that supports .NET Core and NETFX try github.com/adamhathcock/sharpcompress