Navigation |
>> Home |
In a Class of its own - the .NET Zip Library
Written by: Christoph Wille The .NET Framework contains several hundreds of classes, yet something is missing: there is no class for compressing and decompressing Zip archives. This omission however can be made up for by using the .NET Zip Library (NZipLib) - it supports Zip as well as GZip format, is free, and comes with C# source code included. The NZipLib can be downloaded from ic#code. Even though the library itself is distributed under the GPL (GNU General Public License), it may be used in Non-GPL programs thanks to the particular exemption stated on the homepage. Usage under ASP.NETThe library is compiled as a DLL assembly, and can be found in the downloadable Zip file in the NZipLib\src\NZipLib\ directory. The first step then is to copy it into the bin directory of the Web site. Now that the component already is registered thanks to XCOPY Deployment, it can be used immediately. To this end, I have written a small ASP.NET page which lists the contents of a Zip archive: the filename, the file size, the compressed size. The source code is contained in the download for today's article as ListZipContent.aspx: <% @Page Language= "C#" %> <% @Import Namespace="System.IO" %> <% @Import Namespace="System.Text" %> <% @Import Namespace="NZlib.Zip" %> <% ZipInputStream s = new ZipInputStream(File.OpenRead("c:\\test.zip")); ZipEntry theEntry = null; StringBuilder strOutput = new StringBuilder(); while ((theEntry = s.GetNextEntry()) != null) { strOutput.Append("<tr><td>"); strOutput.Append(theEntry.Name); strOutput.Append("</td><td>"); strOutput.Append(theEntry.Size.ToString()); strOutput.Append("</td><td>"); strOutput.Append(theEntry.CompressedSize.ToString()); strOutput.Append("</td></tr>\r\n"); } s.Close(); // clean up the file resource immediately %> <table> <tr><th>File name</th><th>Actual Size</th><th>Compressed Size</th></tr> <% Response.Write(strOutput.ToString()); %> </table> This example uses the classes of the NZlib.Zip namespace, thus we need a corresponding Import statement. You may refer to a detailed description of all namespaces and classes in the NZipLib\doc\api\Documentation.chm help file. This documentation is similar to the .NET Framework reference, navigation should thus not be a problem. In the above example, I use the ZipInputStream class to access an already existing (hard coded) Zip file. After opening the archive, I traverse all entries of the ZipEntry class using a while loop and buffer the table content generated in a StringBuilder object. The output is pretty unspectacular but represents proof that it works as planned: Viewing Files in ArchivesWe now have a list of files - but how can we access their content? In other words, how do we decompress the individual files? As for this, a modified example, intended to be run at the command line (ViewZipFile.cs): using System; using System.Text; using System.IO; using NZlib.Zip; class MainClass { public static void Main(string[] args) { ZipInputStream s = new ZipInputStream(File.OpenRead(args[0])); ZipEntry theEntry; int nBytes = 2048; byte[] data = new byte[2048]; while ((theEntry = s.GetNextEntry()) != null) { Console.WriteLine(theEntry.Name); Console.Write("Eintrag anzeigen? (j/n)"); if (Console.ReadLine() == "j") { while((nBytes = s.Read(data, 0, data.Length)) > 0) { Console.Write(new ASCIIEncoding().GetString(data,0,nBytes)); } } Console.WriteLine(); } s.Close(); } } Basically, reading a compressed file from the Zip archive is just using the Read command, already well known from handling streams. We process the data obtained so that they are output to the Console encoded as ASCII. Of course, instead of converting, the data might be written to a file on the disk. Compilation of this application is done as follows (Assumption: NZipLib.dll resides in the same directory as the source code): csc /target:exe /reference:NZipLib.dll ViewZipFile.cs It is called like this: viewzipfile c:\test.zip And presto, we can view the files in the Zip archive. Creating Zip ArchivesReading is easy! But what about creating a Zip archive? Well, let us take a look at a small sample program which writes all files in a given subdirectory to a Zip file (CreateZipFile.cs): using System; using System.IO; using NZlib.Zip; class MainClass { public static void Main(string[] args) { // all Files in the given Folder will be compressed string[] aFilenames = Directory.GetFiles(args[0]); // the name of the Zip File is the second Parameter passed in calling ZipOutputStream s = new ZipOutputStream(File.Create(args[1])); // Set compression level: 0 [none] - 9 [highest] s.SetLevel(5); for (int i=0; i < aFilenames.Length; i++) { FileStream fs = File.OpenRead(aFilenames[i]); // normally, the Buffer is allocated once, // here we do it once per File for clarity's sake byte[] buffer = new byte[fs.Length]; fs.Read(buffer, 0, buffer.Length); // and now we write a ZipEntry & the Data ZipEntry entry = new ZipEntry(aFilenames[i]); s.PutNextEntry(entry); s.Write(buffer, 0, buffer.Length); } s.Finish(); s.Close(); } } In the compression scenario, we are working with the ZipOutputStream class, which will be with us when creating the archive. Basically, it is an inversion of the process of unzipping: here we create a ZipEntry, and instead of reading the file from the archive, we write it to the archive. Usage of the program is as follows: createzipfile c:\folder c:\zipfile.zip Personally I think that creating an archive is not at all harder than reading files from an archive. ConclusionToday, I only demonstrated the use of the Zip classes in the library. However, the GZip classes can be used in analogy, as they were derived from the same base classes. Zip ahoi! Downloading the CodeClick here to start the download. Links
©2000-2004 AspHeute.com |