5,693,062 members and growing! (17,728 online)
Email Password   helpLost your password?
General Programming » Algorithms & Recipes » General     Intermediate License: The Code Project Open License (CPOL)

ZipStorer - A Pure C# Class to Store Files in Zip

By Jaime Olivares

Small C# .NET 2.0 class to store and extract uncompressed files in new or existing Zip files, without any external library
C# 2.0, C#, Windows, .NET CF, Mobile, .NET, .NET 2.0Visual Studio, VS2008, Dev

Posted: 23 Nov 2007
Updated: 4 Oct 2008
Views: 32,192
Bookmarked: 127 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
44 votes for this Article.
Popularity: 7.42 Rating: 4.51 out of 5
2 votes, 4.5%
1
0 votes, 0.0%
2
0 votes, 0.0%
3
10 votes, 22.7%
4
32 votes, 72.7%
5
Zip_Storer - Click on image to enlarge

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 and 3.5 Frameworks come with the ZipPackage class, but it is not available in a .NET 2.0 or Compact Framework 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.

Screenshot - Zip_Structure.png

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) to collect each directory entry. The class has been declared inside the System.IO namespace. The following diagram describes all the ZipStorer class members:

Screenshot - Class_Diagram.png

There is no default constructor. There are two ways to construct a new ZipStorer instance, depending on your needs: use either Create() or Open() static methods. To create a new Zip file, use the Create() method like this:

ZipStorer zip = ZipStorer.Create(filename, comment);

You have to specify the full path for the new zip file, and optionally add a comment. To open an existing zip file for appending, you have to use the Open() method, like the following:

ZipStorer zip = ZipStorer.Open(filename, fileaccess);

Where fileaccess should be of type System.IO.FileAccess enumeration type. 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. Also you have to specify the operation type: creating or appending. Once you press the Proceed button, the following code snippet will be executed:

ZipStorer zip;

if (this.RadioCreate.Checked)
    // Creates a new zip file
    zip = ZipStorer.Create(TextStorage.Text, "Generated by ZipStorer class");
else
    // Creates a new zip file
    zip = ZipStorer.Open(TextStorage.Text, FileAccess.Write);

// Stores all the files into the zip file
foreach (string path in listBox1.Items)
{
    zip.AddFile(path, Path.GetFileName(path), "");
}

// Creates a memory stream with text
MemoryStream readme = new MemoryStream(
System.Text.Encoding.UTF8.GetBytes(string.Format("{0}\r\nThis file
    has been {1} using the ZipStorer class, by Jaime Olivares.",
DateTime.Now, this.RadioCreate.Checked ? "created" : "appended")));

// Stores a new file directly from the stream
zip.AddStream("readme.txt", readme, DateTime.Now, "Please read");
readme.Close();

// Updates and closes the zip file
zip.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.

Extracting Stored Files

A new feature added to this class is extraction. To extract a file, you have to first read the zip directory, by using the ReadCentralDir() method, and then the ExtractStoredFile() method, like in the following minimal sample code:

// Open an existing zip file for reading
ZipStorer zip = ZipStorer.Open(@"c:\data\sample.zip", FileAccesss.Read);

// Read the central directory collection
List<ZipStorer.ZipFileEntry> dir = zip.ReadCentralDir();

// Look for the desired file
foreach (ZipStorer.ZipFileEntry entry in dir)
{
    if (Path.GetFileName(entry.FilenameInZip) == "sample.jpg")
    {
        // File found, extract it
        zip.ExtractStoredFile(entry, @"c:\data\sample.jpg");
        break;
    }
}
zip.Close();

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 external libraries, no extra DLLs in your deployments
  • No Interop calls, increments portability, maybe to Mono
  • Can also be implemented with .NET Compact Framework
  • Fast storing and extracting, 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 without any restriction. Hope you find it useful.

History

  • November 23rd, 2007: First version
  • June 1st, 2008: Added append and extraction features
  • June 20th, 2008: Corrected some bugs in extraction portion
  • August 3rd, 2008: Corrected more bugs in extraction portion
  • October 3rd, 2008: Improved demo application with extraction code sample

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Jaime Olivares




Computer Electronics professional and senior Windows C++ and C# developer with experience in many other programming languages, platforms and application areas including communications, simulation systems, GIS, graphics and mobile issues.
Also have experience in electronic interfaces development, specially for military applications.
Currently intensively working with Visual C# 2008.
Top-100 contributor at Experts-Exchange forum.
If you have an interesting project, you can contact him at: jaimeolivares.com
Occupation: Software Developer (Senior)
Company: Freelance contractor
Location: Peru Peru

Other popular Algorithms & Recipes articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 25 of 73 (Total in Forum: 73) (Refresh)FirstPrevNext
GeneralAdding Files of Size 0memberInedita704:52 6 Nov '08  
GeneralRe: Adding Files of Size 0memberJaime Olivares18:18 12 Nov '08  
GeneralUnzipping files with directory und subdirectorymemberMember 403358721:21 6 Oct '08  
GeneralRe: Unzipping files with directory und subdirectorymemberJaime Olivares21:29 6 Oct '08  
GeneralRe: Unzipping files with directory und subdirectorymemberMember 403358722:06 6 Oct '08  
GeneralRe: Unzipping files with directory und subdirectorymemberJaime Olivares22:08 6 Oct '08  
GeneralRe: Unzipping files with directory und subdirectorymemberMember 403358722:23 6 Oct '08  
GeneralNew VB Version [modified]memberJohnny J.22:33 5 Oct '08  
GeneralRe: New VB VersionmemberJaime Olivares0:33 6 Oct '08  
GeneralOther pure C# alternativesmemberRednaxelaFX4:05 4 Oct '08  
Generaladd compression supportmemberUnruled Boy16:43 15 Sep '08  
GeneralRe: add compression supportmemberJaime Olivares8:32 3 Oct '08  
GeneralProblem for descompact ImagememberMember 40906879:44 22 Aug '08  
GeneralRe: Problem for descompact ImagememberJaime Olivares16:44 25 Aug '08  
NewsWhat about...memberSuper Lloyd20:31 12 Aug '08  
GeneralRe: What about...memberJaime Olivares18:59 16 Aug '08  
GeneralSmall Oversightmembersmesser4:45 6 Aug '08  
GeneralRe: Small OversightmemberJaime Olivares8:37 6 Aug '08  
QuestionExtraction bug?memberwendykcook1:32 23 Jul '08  
AnswerRe: Extraction bug?memberJaime Olivares1:45 23 Jul '08  
AnswerRe: Extraction bug?memberJaime Olivares17:01 5 Aug '08  
Generalabout ExtractStoredFile() function bugmemberjoseph_tu20:54 21 Jul '08