JavaEnterprise JavaAccessing zips and jars using Java Part 1

Accessing zips and jars using Java Part 1

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.


In this part, we’ll cover how to get the table of contents of a zip file and a jar file and how to get the manifest of a jar file. In part two (next week), we’ll look at how to create, add files to, and extract files from zip files and jar files.

Tools

Here are the tools you will need to write Java programs that access zip and jar files:

  • The Java Development Kit (JDK) version 1.1 or version 1.2 (Java 2). If you want to access zip files only, or want to access jar files as zip files, then JDK 1.1 will do. If you want to access both zip files and jar files, you will need Java 2.
  • Your favorite text editor.
Note that you should also be able to use any of the Java IDE tools that are available, such as Java Workshop, Visual Cafe, or JBuilder. However, some of these tools do not yet support Java 2.

Java 2 changes

Java 2 has the following changes from JDK 1.1 related to zip files and jar files:

  • ZipFile.size()
    was added. It returns the number of entries in the zip file.
  • ZipEntry.ZipEntry(ZipEntry e) 
    was added. It is used to construct a new zip entry using the attributes of another zip entry.
  • ZipEntry.clone()
    was added. It is used to obtain a copy of a zip entry.
  • ZipEntry.hashCode()
    was added. It returns the hash code for the zip entry.
  • Package java.util.jar was added. It contains classes for operating on jar files.

ZIP contents

Getting the table of contents of a jar file may seem difficult at first, but actually it is not. You use the ZipFile and ZipEntry classes, which are contained in package java.util.zip, and the Enumeration interface, which is contained in package java.util. Here is an example program, ZipView, that gets the table of contents of a zip file and displays it. Sample output is here.

The algorithm for ZipView is very straightforward:

  1. Open the zip file by creating a ZipFile, passing the zip file name to the constructor.
  2. Get an Enumeration of the zip entries.
  3. Loop through the entries. For each entry, cast it to a ZipEntry, then print the name of the entry.
  4. Close the zip file.

Note that I enclosed the main loop in a

try {…}
block with a finally clause. This makes sure that the zip file is closed, even if an exception is thrown.

If you lookup the ZipFile class in the JDK documentation, you will see that

entries()
returns Enumeration. “The Enumeration interface provides a simple and consistent way to loop through all of the elements contained within some kind of object or data structure.” [1]

To determine if there are more elements available, you call

Enumeration.hasMoreElements()
. To get the next available element, you call

Enumeration.nextElement()
, which returns Object, which you have to cast to the class that you need. Also, you can only loop through an Enumeration once; there is no way to go back to the beginning. That is why in ZipView, I declared “entries” in the initialization part of the

for(;;)
loop. When the loop is done, “entries” is not useful, so I might as well let the garbage collector have it.

JAR contents

Jar files are zip files with a manifest, which contains meta-information about the jar and the files in the jar. So, getting the table of contents of a jar file works like getting the table of contents of a zip file; but instead of the ZipFile and ZipEntry classes, you use the JarFile and JarEntry classes, which are contained in package java.util.jar. (You actually can use the zip classes, but you won’t have access to the manifest.) Here is an example program, JarView, that gets the table of contents of a jar file and displays it. Sample output is here.

JAR manifest

Getting the manifest of a jar file (without extracting it as a file) is slightly more difficult than getting the table of contents. This is because you have to get the manifest attributes and the manifest entries, which themselves have attributes, and because you have to you use the new collection interfaces, which are somewhat more complex than the Enumeration interface in JDK 1.1. In addition to the JarFile class, you use the Manifest and Attributes classes, which are contained in package java.util.jar, and you use the Map, Map.Entry, Set, and Iterator interfaces, which are contained in package java.util. Here is an example program, JarManifest, that gets the manifest of a jar file and displays it. Sample output is here.

The algorithm for JarManifest is fairly straightforward:

  1. Open the jar file.
  2. Get the manifest by calling

    jar.getManifest()
    .
  3. Get an Iterator for the manifest attributes.
  4. Loop through the manifest attributes. For each attribute, cast it to Map.Entry, then print the key and the value (e.g., Foo: 1).
  5. Get an Iterator for the manifest entries.
  6. Loop through the manifest entries. For each entry, cast it to Map.Entry, print the key, then:
    1. Get an Iterator for the entry attributes.
    2. Loop through the manifest entry attributes. For each attribute, cast it to Map.Entry, then print the key and value.
  7. Close the jar file.
If you lookup the Manifest class in the JDK documentation, you will see

getEntries()
returns Map, and

getMainAttributes()
returns Attributes, which implements Map. The Map interface is used to operate on key-value mappings and provides methods for getting multiple views of the mapping: the keys, the values, or the set of key-value pairs. To get the set of key-value pairs, you call

Map.entrySet()
, which returns Set. The Set interface is used to operate on sets of key-value pairs. To loop through a Set, you use an Iterator instead of an Enumeration. To get an Iterator, you call

Set.iterator()
. Thus, the code to get an Iterator for the jar manifest attributes looks like this:


Iterator entries =
manifest.getMainAttributes().entrySet().iterator();

And, the code to get an Iterator for the attributes of a manifest entry looks like this:


Iterator attributes =
(Attributes entry.getValue()).entrySet().iterator();

(Note the cast to Attributes. This is necessary because

entry.getValue()
returns Object.)

Additionally, Map has an inner interface, Map.Entry. This interface is used to operate on the key-value pairs that are contained in a Map. Thus, when you get an element from the Iterator for a Set that was returned by

Map.entrySet()
, you have to cast the element to Map.Entry before you can get the key and the value.

Resources

References

[1] Java in a Nutshell, Second Edition. Flanagan, David. Copyright 1997, 1996. O’Reilly & Associates, Inc.

About the author

Thornton Rose is a software developer who lives and works in Atlanta, Georgia. He can be reached via e-mail at trose@avana.net.


Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories