You could use the jar program in the Java
Development Kit, since its file format is identical with the zip
format with the addition of the META-INF directory to contain
additional structural information. But since this is a book about
programming, you are probably more interested in the
ZipFile
and
ZipEntry
classes and the stream classes that they
provide access to.
The class
java.util.zip.ZipFile
is not an I/O class per se, but a utility
class that allows you to read or write the contents of a JAR or
zip-format file.[25] When constructed, it creates a series of
ZipEntry
objects, one to represent each entry in
the archive. In other words, the ZipFile
represents the entire archive, and the ZipEntry
represents one entry, or one file that has been stored (and
compressed) in the archive. The
ZipEntry
has methods like getName( )
, which returns the name that the file had before it was
put into the archive, and getInputStream( )
, which gives you an
InputStream
that will transparently uncompress the
archive entry by filtering it as you read it. To create a
ZipFile
object, you need either the name of the
archive file or a File
object representing it:
ZipFile zippy = new ZipFile(fileName);
If you want to see whether a given file is present in the archive,
you can call the getEntry( )
method with a
filename. More commonly, you’ll want to process all the
entries; for this, use the ZipFile
object to get a
list of the entries in the archive, in the form of an
Enumeration
(see Section 7.5):
Enumeration all = zippy.entries( ); while (all.hasMoreElements( )) { ZipEntry entry = (ZipEntry)all.nextElement( );
We can then process each entry as we wish. A simple listing program could be:
if (entry.isDirectory( )) println("Directory: " + e.getName( )); else println("File: " + e.getName( ));
A fancier version would extract the files. The program in Example 9-4 does both: it lists by default, but with the
-x
(extract) switch, it actually extracts the
files from the archive.
Example 9-4. UnZip.java
import java.io.*; import java.util.*; import java.util.zip.*; /** * UnZip -- print or unzip a JAR or PKZIP file using JDK1.1 java.util.zip. * Final command-line version: extracts files. */ public class UnZip { /** Constants for mode listing or mode extracting. */ public static final int LIST = 0, EXTRACT = 1; /** Whether we are extracting or just printing TOC */ protected int mode = LIST; /** The ZipFile that is used to read an archive */ protected ZipFile zippy; /** The buffer for reading/writing the ZipFile data */ protected byte[] b; /** Simple main program, construct an UnZipper, process each * .ZIP file from argv[] through that object. */ public static void main(String[] argv) { UnZip u = new UnZip( ); for (int i=0; i<argv.length; i++) { if ("-x".equals(argv[i])) { u.setMode(EXTRACT); continue; } String candidate = argv[i]; // System.err.println("Trying path " + candidate); if (candidate.endsWith(".zip") || candidate.endsWith(".jar")) u.unZip(candidate); else System.err.println("Not a zip file? " + candidate); } System.err.println("All done!"); } /** Construct an UnZip object. Just allocate the buffer */ UnZip( ) { b = new byte[8092]; } /** Set the Mode (list, extract). */ protected void setMode(int m) { if (m == LIST || m == EXTRACT) mode = m; } /** For a given Zip file, process each entry. */ public void unZip(String fileName) { try { zippy = new ZipFile(fileName); Enumeration all = zippy.entries( ); while (all.hasMoreElements( )) { getFile(((ZipEntry)(all.nextElement( )))); } } catch (IOException err) { System.err.println("IO Error: " + err); return; } } /** Process one file from the zip, given its name. * Either print the name, or create the file on disk. */ protected void getFile(ZipEntry e) throws IOException { String zipName = e.getName( ); if (mode == EXTRACT) { // double-check that the file is in the zip // if a directory, mkdir it (remember to // create intervening subdirectories if needed!) if (zipName.endsWith("/")) { new File(zipName).mkdirs( ); return; } // Else must be a file; open the file for output System.err.println("Creating " + zipName); FileOutputStream os = new FileOutputStream(zipName); InputStream is = zippy.getInputStream(e); int n = 0; while ((n = is.read(b)) >0) os.write(b, 0, n); is.close( ); os.close( ); } else // Not extracting, just list if (e.isDirectory( )) { System.out.println("Directory " + zipName); } else { System.out.println("File " + zipName); } } }
[25] There is no support for adding files to an existing archive, so make sure you put all the files in at once, or be prepared to re-create the file from scratch.
18.190.217.253