![]() |
General Programming »
Algorithms & Recipes »
General
Intermediate
License: The Code Project Open License (CPOL)
ZipStorer - A Pure C# Class to Store Files in ZipBy Jaime OlivaresSmall C# class to store and extract uncompressed and deflated files in new or existing Zip files, without any external library. |
C# (C#2.0), Windows, .NETCF, .NET (.NET2.0), Visual-Studio (VS2008), Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
There are many techniques to produce Zip files in a .NET 2.0 environment, like the following:
java.util.zip namespace 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 with basic compression or plain storing. I have built my own minimalistic class to create Zip files and store/retrieve files to/from it, firstly with uncompressed storing capabilities and now with Deflate algorithm. no other compression methods supported.
Moreover, notice that the new .NET 3.0 and 3.5 Frameworks come with the ZipPackage class, but it is not available for .NET 2.0 or Compact Framework applications. A restriction of ZipPackage is that you cannot avoid generating an extra file inside named [Content_Type].xml.
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.
The ZipStorer class is the unique one needed to create the zip 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:
There is no default constructor. There are two ways to construct a new ZipStorer instance, depending on specific 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. Also, as now ZipStorer is derived from IDisposable interface, the using keyword can be used to ensure proper disposing of the storage resource:
using (ZipStorer zip = ZipStorer.Create(filename, comment))
{
// some operations with zip object
//
} // automatic close operation here
To add files into an opened zip storage, there are two available methods:
public void AddFile(ZipStorer.Compress _method, string _pathname, string _filenameInZip,
string _comment);
public void AddStream(ZipStorer.Compress _method, string _filenameInZip, Stream _source,
DateTime _modTime, string _comment);
The first method allows you to add an existing file to the storage. The first argument receives the compression method; it can be Store or Deflate enum values. The second argument admits the physical path name, the third one allows 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. Alternatively, you can use Dispose() method.
The provided sample application will ask for files and store the path names in a ListBox, along with the operation type: creating or appending, and compression method. Once the Proceed button is pressed, 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(this.checkCompress.Checked ?
ZipStorer.Compression.Deflate : ZipStorer.Compression.Store,
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. The solution cannot be loaded directly with Visual Studio 2005, but a new solution can be created and the project file attached to it without problems.
To extract a file, the zip directory shall be read first, 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();
Removal of entries in a zip file is a resource-consuming task. The simplest way is to copy all non-removed files into a new zip storage. The RemoveEntries() static method will do this exactly and will construct the ZipStorer object again. For the sake of efficiency, RemoveEntries() will accept many entry references in a single call, as in the following example:
List<ZipStorer.ZipFileEntry> removeList = new List<ZipStorer.ZipFileEntry>();
foreach (object sel in listBox4.SelectedItems)
{
removeList.Add((ZipStorer.ZipFileEntry)sel);
}
ZipStorer.RemoveEntries(ref zip, removeList);
ZipStorer has the following advantages:
To implement this class into your own project, just add the ZipStorer.cs class file and start using it without any restriction. More recent updates can be found at my CodePlex page (zipstorer.codeplex.com).
General
News
Question
Answer
Joke
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 4 Oct 2009 Editor: Deeksha Shenoy |
Copyright 2007 by Jaime Olivares Everything else Copyright © CodeProject, 1999-2010 Web19 | Advertise on the Code Project |