Saturday, December 15, 2012

.Net Framework 4.5 and Compression

In this post we are going to discuss the new features in System.IO.Compression introduced in .net framework 4.5. We are going to specially discuss how easy is to create zip archives using those new features. We are also going to discuss how to use the zip packages and extract from it using a simple project.

ZipArchive in .net 4.5
Let's create a new .net 4.5 project AppCompression. It's a console application based project.

Let's add the references of System.IO.Compression and System.IO.Compression.FileSystem assemblies to the project. Here System.IO.Compression has additional types and extensions to ease working with compression / decompression.

Let's also add a test folder with some files as follows:

The folder also has a sub-folder. The contents of the sub-folder are shown below:

ZipArchive is introduced in .net framework 4.5. It allows us to create a zipped package / compressed file. All individual files are added as entries to the package. The confirms to universal zip format. This zip file can be transmitted and decompressed using a regular decompression utility including Winzip. The following code uses ZipArchive to compress a folder. We are using the main folder discussed above as the source folder. As you can see, we are creating a ZipArchive instance and adding individual files as entries from the folder.

As expected, when executed, the above creates a zip file in the specified path. We notice that it hasn't maintained the folder hierarchy in the compressed file. So we would not be able to decompress this file with the same folder structure as the original uncompressed folder.

As a matter of fact, ZipArchive does support maintaining the folder hierarchy. We just need to specify the file name including the relative path. This should be enough information for ZipArchive to create the intended folder structure. In the code below, we are using Uri.MakeRelativeUri to determine the relative path of each entry using the base folder's path. Now this relative path is used to create entries as follows:

When we look at the compressed folder in Windows Explorer, we do see the folder hierarchy being maintained. It creates the sub folder and adds the intended files to the sub folder. The folder looks as follows:

If we don't want to add System.IO.Compression.FileSystem assembly reference then we can create a simple ZipArchiveEntry from the ZipArchive instance. We can then use stream to copy the file's contents to the ZipArchiveEntry. The following code can be used to replace ZipArchive.CreateEntryFromFile method provided as an extension method to ZipArchive type in System.IO.Compression.FileSystem assembly.

ZipArchive can also be used to decompress a zip file in a directory. First let us see the easier way to do it. There are extension methods for ZipArchive available in System.IO.Compression.FileSystem assembly to do the same. The below code ExtractToDirectory extension method to decompress a zip file to the specified folder. The method extracts the contents of the compressed file while still maintaining the folder hierarchy. As you can see, we can use ZipArchiveMode.Read as we don't need to write any new entries to the package.

We can also enumerate through the entries in a ZipArchive and decompress each entry. In order to maintain the folder hierarchy, ZipArchiveEntry's FullName method can be used. The ExtractToDirectory method can be replaced with the following code. The code would take care of creating the expected folder structure for the compressed file:

ZipFile in .net 4.5
ZipFile is an easier alternative in .net 4.5 for working with compression / decompression. It also supports opening a ZipArchive, we can use it to add entries to a package. The package can later be used to create and save a new / same compressed file.

How simple is that?? Now let's see how we can use ZipFile to extract and compressed file into a folder. The following code extracts the contents of a zip file into the specified folder. We don't even have to make any extra effort to maintain the folder hierarchy during the extraction, ZipFile automatically takes care of that.

As discussed earlier, ZipFile can also be used to Open a compressed file. There are two overloads of Open() which allow us to load a compressed file using either of Read / Create or Update ZipArchiveMode. There is another method, OpenRead(), which opens the compressed package in Read mode. These modes apply restrictions on what we can do with the returned ZipArchive instance. The following sample code uses ZipFile to open a compressed package and writing the names of the entries on the console.

It results in the following output:

Download Code

No comments: