- Download PKWare Zip file specification - 12.8 KB
- Download source - 4.6 KB
- Download sample application - 47.2 KB
Introduction
There are many techniques to produce Zip files in a .NET 2.0 environment, like the following:
- Using the
java.util.zip
namespace - Invoking Shell API features
- Using a third-party .NET library
- Wrapping and marshalling a non-.NET library
- Invoking a compression tool at command-line
I have tested most of them, each one has pros and cons, but sometimes I just needed a tiny library to store files in a Zip without compression, like JPEG images, that are yet inherently compressed. I have read some C++ articles about Zip creation (like this one and others), and built my own minimalistic class to create Zip packages and store files in it.
If you are looking for a true compression class, please do not disqualify this article.
Moreover, notice that the new .NET 3.0 Framework comes with the ZipPackage
class, but it is not available in a .NET 2.0 application, and has some complex interface.
Background
The following diagram depicts a Zip file structure; you will notice it is a bit redundant because of its double directory approach (local and central). This is because it is designed to support creation in a sequential-access-only device.
The contents of each section can vary depending on the Operating System and hardware platform. The original PKWare
specification has been included with this article.
Using the Code
The ZipStorer
class is the unique one that you need to create the storage file. It contains a nested structure (ZipFileEntry
), but it is not exposed to the user. The class has been declared inside the System.IO
namespace. The following diagram describes all the ZipStorer
class members:
Use the constructor to create a new Zip storage. Optionally, you can specify a general comment for the Zip file.
To add files into it, there are two available methods:
public void AddFile(string _pathname, string _filenameInZip, string _comment);
public void AddStream(string _filenameInZip, Stream _source,
DateTime _modTime, string _comment);
The first method allows you to add an existing file to the storage. The first argument admits the physical path name, the second one allows you to change the path or file name to be stored in the Zip, and the last argument inserts a comment in the storage. Notice that the folder path in the _pathname
argument is not saved in the Zip file. Use the _filenameInZip
argument instead to specify the folder path and filename. It can be expressed with both slashes or backslashes.
The second method allows you to add data from any kind of stream
object derived from the System.IO.Stream
class. Internally, the first method opens a FileStream
and calls the second method.
Finally you have to close the storage with the Close()
method. This will save the central directory information too.
Sample Application
The provided sample application will ask for files and store the path names in a ListBox
. Once you press the Proceed button, the following code snippet will be executed:
// Creates a new zip file, giving pathname and comment
ZipStorer zfw = new ZipStorer(textBox1.Text, "Generated by ZipStorer class");
// Stores all the files into the zip file
foreach (string path in listBox1.Items)
{
zfw.AddFile(path, Path.GetFileName(path), "");
}
// Creates a memory stream with text
MemoryStream readme = new MemoryStream(
System.Text.Encoding.UTF8.GetBytes
("This file has been generated using the ZipStorer class,
by Jaime Olivares."));
// Stores a new file directly from the stream
zfw.AddStream("readme.txt", readme, DateTime.Now, "Please read");
readme.Close();
// Updates and closes the zip file
zfw.Close();
This code snippet shows how to add both physical files and a little readme text from a memory stream.
Notice that the sample has been produced with Visual Studio 2008. You cannot load the solution with Visual Studio 2005 directly, but you can create a new solution and attach the project file without problems.
Advantages and Usage
My proposal has the following advantages:
- It is a short and monolithic C# class that you can embed in your project
- No Interop calls, increments portability, maybe to Mono
- No external libraries, no extra DLLs in your deployments
- Fast storing, because the code is simple and short
To implement this class into your own project, just add the ZipStorer.cs class file and start using it. Hope you find it useful.
History
- November 23rd, 2007: First version