This tutorial will teach you how to unzip compressed files using the new namespace of .NET 2.0, System.IO.Compression, which contains the GZipStream class that allows us to decompress compressed ZIP files.
Compressing (zipping) In the previous tutorial entitled Zipping files using GZipStream we reviewed how to compress files using the System.IO.Compression namespace, and we also learned that the GZipStream class of this namespace has some limitations. If you haven’t read that tutorial, I suggest that you read it, and among other things you will learn that we can’t compress multiple files into a single archive and/or give them each a file name like you are used to when using popular tools such as WinRAR or WinZIP. Details on why this isn’t possible and what workaround is available are in that tutorial.
This means we also can’t decompress ZIP archives that have multiple files or a filename header defined in them. Basically it is recommended that you only decompress files that were compressed using the GZipStream. If you’re looking to build an application similar to WinRAR or WinZIP, you would probably be better with a 3rd party class library that has more functionality or – if you have enough experience – extending the GZipStream class to include the missing functionality.
Decompressing (unzipping, sample application) Start by creating a new Windows application project into Visual Studio 2005. Add to the form a TextBox and two Buttons. The TextBox is entitled txtPath and it will hold the path to the file to decompress. The Buttons are entitled btnBrowse and btnDecompress. The first one will show an OpenFileDialog for picking a ZIP file to decompress, and the second one – btnDecompress – will show a SaveFileDialog followed by the actual decompressing and saving process. Finally, make sure you add an OpenFileDialog and SaveFileDialog to our application and name them openFile and saveFile.
Among the already existent namespaces, add the following two at the top of the class file:
using System.IO;
using System.IO.Compression;
Now double click btnBrowse and its Click event will be created. Inside it use the following code that displays the OpenFileDialog and allows the user to pick a file to decompress:
// Show the dialog where the user chooses the file to decompress
if (openFile.ShowDialog() == DialogResult.OK)
{
txtPath.Text = openFile.FileName;
}
Now double click the btnDecompress button so that you get to its click event and inside it use the following code which will take the compressed file and try to decompress it.
// If the user has selected a path where to put the decompressed file
if (saveFile.ShowDialog() == DialogResult.OK)
{
// Bytes array in which we're going to store the actual file to be decompressed
byte[] bufferWrite;
// Will open the file to be decompressed
FileStream fsSource;
// Will write the new decompressed file
FileStream fsDest;
// To hold the compressed file
GZipStream gzDecompressed;
fsSource = new FileStream(txtPath.Text, FileMode.Open, FileAccess.Read, FileShare.Read);
// Will hold the compressed stream created from the destination stream
gzDecompressed = new GZipStream(fsSource, CompressionMode.Decompress, true);
// Retrieve the size of the file from the compressed archive's footer
bufferWrite = new byte[4];
fsSource.Position = (int)fsSource.Length - 4;
// Write the first 4 bytes of data from the compressed file into the buffer
fsSource.Read(bufferWrite, 0, 4);
// Set the position back at the start
fsSource.Position = 0;
int bufferLength = BitConverter.ToInt32(bufferWrite, 0);
byte[] buffer = new byte[bufferLength + 100];
int readOffset = 0;
int totalBytes = 0;
// Loop through the compressed stream and put it into the buffer
while (true)
{
int bytesRead = gzDecompressed.Read(buffer, readOffset, 100);
// If we reached the end of the data
if (bytesRead == 0)
break;
readOffset += bytesRead;
totalBytes += bytesRead;
}
// Write the content of the buffer to the destination stream (file)
fsDest = new FileStream(saveFile.FileName, FileMode.Create);
fsDest.Write(buffer, 0, totalBytes);
// Close the streams
fsSource.Close();
gzDecompressed.Close();
fsDest.Close();
}
Try to decompress a ZIP archive created using WinZIP or a similar application, and it should come as no suprise that the application we built here won’t work for the reasons mentioned at the beginning of the tutorial. If you try compressing the file using the application we built in the previous tutorial the decompressing is guaranteed to work.