4.10 Using Zip, GZip, Tar, and BZip2 Archives in Your Software with SharpZipLib

Compression isn’t just for smashing up scads of text or binary data into archives; it’s also a critical element for efficient transport of data from one network endpoint to another. SharpZipLib, brought to you by the same folks at ic#code who created the SharpDevelop open source .NET IDE, can help you by compressing any data stream you’re working with.

SharpZipLib at a Glance

Tool

SharpZipLib

Version covered

0.84

Home page

http://www.icsharpcode.net/OpenSource/SharpZipLib/

Power Tools page

http://www.windevpowertools.com/tools/151

Summary

Work with Zip, GZip, Tar, and BZip2 files via this library written entirely in C#

License type

Modified GPL; usable for commercial closed-source apps, but read the license

Online resources

Forum

Supported Frameworks

.NET 1.1, 2.0

Getting Started

SharpZipLib is available in several different distributions. You can download a compiled assembly complete with scripts for installing in your system’s GAC, or you can grab source code and build the assemblies yourself.

Because SharpZipLib’s source code was created in SharpDevelop, you’ll need that IDE to work with the source’s project files. NAnt build scripts are included with the source, so you have an option for building if you’re not currently using SharpDevelop.

Using SharpZipLib

SharpZipLib’s GZip and Zip compression routines use the same basic process: create a stream for the zip type, write some bytes to it, and then close it. An example for GZip’s simplest incarnation is shown in Example 4-4.

Example 4-4. Using GZip with a single file

private void SingleGZip(string source)
{
    string target = source + ".gz";

    using (Stream s = new GZipOutputStream(File.Create(target)))
    {
        using (FileStream fs = File.OpenRead(source))
        {
            byte[] buffer = new byte[fs.Length];
            fs.Read(buffer, 0, (int) fs.Length);
            s.Write(buffer, 0, buffer.Length);
        }
    }
}

Example 4-5 shows the simplicity of extracting a file from a GZip archive.

Example 4-5. Extracting a GZip file

using (Stream input = new GZipInputStream(File.OpenRead(source)))
{
    using (FileStream output =
            File.Create(Path.GetFileNameWithoutExtension(source)))
    {
        int buffSize = 2048;
        byte[] outBuffer = new byte[2048];
        while (true)
        {
            buffSize = input.Read(outBuffer, 0, buffSize);
            if (buffSize > 0)
            {
                output.Write(outBuffer, 0, buffSize);
            }
            else
            {
                break;
            }
        }
    }
}

Working with BZip2 compression is even easier. Static methods give quick access to compression and decompression functionality. Compressing a file is a simple matter, as shown in Example 4-6.

Example 4-6. Using BZip2 with a single file

private void BZip2Compress(string source)
{
    string target = source + ".bz2";
    int blockSize = 4096;
    BZip2.Compress(File.OpenRead(source), File.Create(target), blockSize);
}

Decompressing likewise involves just a quick call to a static method, as you can see in Example 4-7.

Example 4-7. Extracting a BZip2 file

private void BZip2Decompress(string source)
{
    BZip2.Decompress(File.OpenRead(source),
            File.Create(Path.GetFileNameWithoutExtension(source)));
}

Zip compression works much the same; however, ZipOutputStream objects can make use of the ZipEntry class. ZipEntry objects work nicely when you want to pass in a list of files to add to an archive (say, a list of files a user has selected from a menu). Example 4-8 shows how to archive a list of files.

Example 4-8. Zipping multiple files

private void ZipMultipleCompress(string target, string[] fileNames,
        int compressionLevel)
{
    using (ZipOutputStream zipOutStream = new ZipOutputStream(File.Create(target)))
    {
        zipOutStream.SetLevel(compressionLevel);

        foreach (string file in fileNames)
        {
            using (FileStream inStream = File.OpenRead(file))
            {
                byte[] buffer = new byte[inStream.Length];
                inStream.Read(buffer, 0, buffer.Length);

                ZipEntry entry = new ZipEntry(file);
                zipOutStream.PutNextEntry(entry);
                zipOutStream.Write(buffer, 0, buffer.Length);
            }
        }
    }
}

Another handy feature of the ZipOutputStream enables you to add checksums via SharpZipLib’s Crc32 class. Create a new Crc32 object:

Crc32 crc = new Crc32( );

and then make use of it for each ZipEntry item in your list:

// clear previous CRC, compute new one, add to entry
crc.Reset( );
crc.Update(buffer);
entry.Crc = crc.Value;

There’s also a handy FastZip class that offers quick creation and extraction of Zip files. It has a few restrictions, though: FastZip can’t use absolute file paths, nor is it appropriate for collections of files—it’s better used for files within one directory tree.

Tar archives are fully supported in SharpZipLib as well. The usage pattern is very similar to the Zip method shown in Example 4-8. You’ll have to deal with creating output streams for the different compression types (BZip2, GZip) yourself, but this is straightforward and is well documented in the distribution’s examples.

Getting Support

SharpZipLib has an active community in forums at the library’s home page, where most issues you run into can be resolved quickly.

Get Windows Developer Power Tools now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.