Recently I had to build a private online photo album application.
I planned to provide the users option to upload images as a zip file. I
needed this option to be implemented in ASP.NET 1.1, as my hosting service provider
didn't have .NET 2.0 support. An online search lead me to a blog with this
wonderful idea of using the zip option in J# and it really attracted me. I
wanted to try it out and the results were pretty cool. Even though this sample
application has been written in .NET 2.0, the .NET Framework 2.0 has libraries
to work with the compressing and uncompressing of files. I will soon come up
with an article to illustrate the use of .NET 2.0 libraries with compressing and uncompressing functionalities.
In this article I will explain the usage of zip functionality in J# from C# code.
The code in this application has been designed to reuse in a copy/paste fashion and not as a library.
This application consumes J# classes internally. For this we must first refer
to the J#.NET library. Physically it resides as a file named vjslib.dll. If you
are not very sure how to refer to a library in your project please follow the
Right click your project in Server Explorer and click on "Add Reference"
-> Select the .Net tab -> Scroll down and select "vjslib" -> Click OK
and you are there. Now you can refer the Java library classes within your
This was the first time trying to refer to the J#
classes and it was a moment in my programming life that I will never forget.
Import the following namespaces for ease of coding.
java.util.zip namespace contains the classes and methods to implement the
compress and uncompress functionalities within our code. The main classes used
from the above namespaces are:
ZipFile object can be considered equivalent to a physical
Zip file. A
ZipFile can contain multiple
ZipEntry objects apart from the actual
content of the zipped files. In fact, each
ZipEntry object is the metadata about
a zip file. The
ZipOutputStream class represents a writable stream pointing to a
zip file. This stream can be used to write
ZipEntry objects and content to the
Enumeration enables iteration through each element in a collection.
Using the code
Below is a code listing how to create a zip file.
private void Zip(string zipFileName, string sourceFile)
FileOutputStream filOpStrm = new FileOutputStream(zipFileName);
ZipOutputStream zipOpStrm = new ZipOutputStream(filOpStrm);
FileInputStream filIpStrm = null;
foreach(string strFilName in sourceFile)
filIpStrm = new FileInputStream(strFilName);
ZipEntry ze = new ZipEntry(Path.GetFileName(strFilName));
sbyte buffer = new
int len = 0;
while ((len =
filIpStrm.read(buffer)) > = 0)
zipOpStrm.write(buffer, 0, len);
Zip() method accepts two parameters,
zipFileName - Zip file name including the path and
sourceFile - string array of file names that are to be zipped.
FileOutputStream class is capable of writing content to a file. Its
constructor accepts the path of the file to which we wish to write.
FileOutputStream object is then supplied to an instance of
as parameter. The
ZipOutputStream class represents a writable stream to a zip
foreach loops through each file to be zipped, creates corresponding
zip entries and adds it to the final zip file.
Taking a deeper look into the
FileInputStream object is created for each file to be zipped.
FileInputStream object is capable of reading from a file as a stream. Then a
ZipEntry object is created for each file to be zipped. The constructor of the
ZipEntry class accepts name of the file.
Path.GetFileName() returns the file
name and extension of the specified path string.
The newly created
ZipEntry object is added to the
ZipOutputStream object using its
putNextEntry() method. In fact, a
merely represents metadata of file entry. You still need to add
actual contents into the zip file. Therefore, you need to transfer data from source
FileInputStream to destination
FileOutputStream. This is exactly what the
does in the above piece of code. It reads content from the source file
and writes it into the output zip file. Finally, the
closeEntry() method of
ZipOutputStream class is
called and this caused the physical creation of the zip file. All the other streams created are also closed.
private void Extract(string zipFileName, string destinationPath)
ZipFile zipfile = new ZipFile(zipFileName);
List<ZipEntry> zipFiles = GetZippedFiles(zipfile);
foreach (ZipEntry zipFile in zipFiles)
InputStream s = zipfile.getInputStream(zipFile);
Directory.CreateDirectory(destinationPath + "\\" +
FileOutputStream dest = new
FileOutputStream(Path.Combine(destinationPath + "\\" +
int len = 0;
sbyte buffer = new sbyte;
while ((len = s.read(buffer)) > = 0)
dest.write(buffer, 0, len);
ExtractZipFile() method accepts two parameters: the zip
filename (including path) to be extracted, and destination path where the files
are to be extracted. It then creates a
ZipFile object and retrieves entries in
the ZIP file using the
GetZipFiles() method. This method will be discussed
afterwards in this article. The
for each loop iterates through all the entries in
the zip file and in each iteration the entry is extracted to the specified
folder. The code in the
for each loop executes only if the entry is not a folder. This condition is verified using the
isDirectory() method of
ZipEntry object. Each
entry is read into an
getInputStream() method of
InputStream acts as the source stream. The destination stream is a
FileOutputStream object which is created based on the specified destination
folder. Here we use the
getName() method of
ZipEntry object to get the file
name(including path) of the entry.
During the extraction, the original folder
structure is maintained. In the
while loop that follows, content from the source
InputStream is written to the destination
FileOutputStream. The source stream is
read to a buffer using the
read() method. It reads 7 KB in a sequence into a
temporary buffer and the
write() method of destination
FileOutputStream writes the
content to the stream from the buffer, using the write method. It is in the
final block that follows, the destination
FileOutputStream is closed and the
content is physically written to disk.
private List<ZipEntry> GetZipFiles(ZipFile zipfil)
List<ZipEntry> lstZip = new List<ZipEntry>();
Enumeration zipEnum = zipfil.entries();
ZipEntry zip = (ZipEntry)zipEnum.nextElement();
GetZipFiles() method returns a generic
ZipEntry objects taking a
ZipFile object as argument. The method creates a
generic collection of
ZipEntry type. Now comes the use of an interesting
feature in the Java language, the use of
Enumeration. Note that its not the
enum type that we have in
C#. An object that implements the
Enumeration interface generates a series of
elements, one at a time. Successive calls to the
nextElement() method return
successive elements of the series. The
hasMoreElements() method returns a
boolean value indicating if the
Enumerator contains more elements. Here,
entries() method of
ZipFile class returns an
The code then iterates through the
Enumeration and populates the List. Finally,
the populated List is returned.
Apart from the above listed code, the downloadable
source code for the sample application, contains some extra code to handle the
UI part of the application, i.e., entries made to the ListBox and handling
the progress bar. I haven't included them in this article because I didn't want to lose
focus from the main objective of the article. The code is comprehensive, but the UI
controls can be handled in better ways, keeping performance and usability in
mind. One good option might be to keep our zip functionality separate from the
UI thread, so that interactivity is well maintained.
Points of Interest
One interesting fact we note while using the Java library is
the difference in naming conventions, especially the naming of methods. For C#
coders, methods give the feel of variable names. Also, the way the classes are
named is a distinguishable factor.
Even though we can't use the features of Java
beyond a point because runtime decides the main advantages of a platform; we
would take advantage of using the Java libraries. This gives an upper hand of
Java over C#.
I hope Microsoft continues to support J#.