ZIP File Streams

   


ZIP files are archives that store one or more files in (usually) compressed format. Java 1.1 can handle both GZIP and ZIP format. (See RFC 1950, RFC 1951, and RFC 1952, for example, at http://www.faqs.org/rfcs.) In this section we concentrate on the more familiar (but somewhat more complicated) ZIP format and leave the GZIP classes to you if you need them. (They work in much the same way.)

NOTE

The classes for handling ZIP files are in java.util.zip and not in java.io, so remember to add the necessary import statement. Although not part of java.io, the GZIP and ZIP classes subclass java.io.FilterInputStream and java.io.FilterOutputStream. The java.util.zip packages also contain classes for computing cyclic redundancy check (CRC) checksums. (CRC is a method to generate a hashlike code that the receiver of a file can use to check the integrity of the data.)


Each ZIP file has a header with information such as the name of the file and the compression method that was used. In Java, you use a ZipInputStream to read a ZIP file by layering the ZipInputStream constructor onto a FileInputStream. You then need to look at the individual entries in the archive. The getNextEntry method returns an object of type ZipEntry that describes the entry. The read method of the ZipInputStream is modified to return 1 at the end of the current entry (instead of just at the end of the ZIP file). You must then call closeEntry to read the next entry. Here is a typical code sequence to read through a ZIP file:


ZipInputStream zin = new ZipInputStream(new FileInputStream(zipname));
ZipEntry entry;
while ((entry = zin.getNextEntry()) != null)
{
   analyze entry;
   read the contents of zin;
   zin.closeEntry();
}
zin.close();

To read the contents of a ZIP entry, you will probably not want to use the raw read method; usually, you will use the methods of a more competent stream filter. For example, to read a text file inside a ZIP file, you can use the following loop:


BufferedReader in = new BufferedReader(new InputStreamReader(zin));
String s;
while ((s = in.readLine()) != null)
   do something with s;

The program in Example 12-1 lets you open a ZIP file. It then displays the files stored in the ZIP archive in the combo box at the bottom of the screen. If you double-click on one of the files, the contents of the file are displayed in the text area, as shown in Figure 12-5.

Example 12-1. ZipTest.java
   1. import java.awt.*;   2. import java.awt.event.*;   3. import java.io.*;   4. import java.util.*;   5. import java.util.zip.*;   6. import javax.swing.*;   7. import javax.swing.filechooser.FileFilter;   8.   9. public class ZipTest  10. {  11.    public static void main(String[] args)  12.    {  13.       ZipTestFrame frame = new ZipTestFrame();  14.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  15.       frame.setVisible(true);  16.    }  17. }  18.  19. /**  20.   A frame with a text area to show the contents of a file inside  21.   a zip archive, a combo box to select different files in the  22.   archive, and a menu to load a new archive.  23. */  24. class ZipTestFrame extends JFrame  25. {  26.    public ZipTestFrame()  27.    {  28.       setTitle("ZipTest");  29.       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);  30.  31.       // add the menu and the Open and Exit menu items  32.       JMenuBar menuBar = new JMenuBar();  33.       JMenu menu = new JMenu("File");  34.  35.       JMenuItem openItem = new JMenuItem("Open");  36.       menu.add(openItem);  37.       openItem.addActionListener(new OpenAction());  38.  39.       JMenuItem exitItem = new JMenuItem("Exit");  40.       menu.add(exitItem);  41.       exitItem.addActionListener(new  42.          ActionListener()  43.          {  44.             public void actionPerformed(ActionEvent event)  45.             {  46.                System.exit(0);  47.             }  48.          });  49.  50.       menuBar.add(menu);  51.       setJMenuBar(menuBar);  52.  53.       // add the text area and combo box  54.       fileText = new JTextArea();  55.       fileCombo = new JComboBox();  56.       fileCombo.addActionListener(new  57.          ActionListener()  58.          {  59.             public void actionPerformed(ActionEvent event)  60.             {  61.               loadZipFile((String) fileCombo.getSelectedItem());  62.            }  63.         });  64.  65.      add(fileCombo, BorderLayout.SOUTH);  66.      add(new JScrollPane(fileText), BorderLayout.CENTER);  67.   }  68.  69.   /**  70.      This is the listener for the File->Open menu item.  71.   */  72.   private class OpenAction implements ActionListener  73.   {  74.      public void actionPerformed(ActionEvent event)  75.      {  76.         // prompt the user for a zip file  77.         JFileChooser chooser = new JFileChooser();  78.         chooser.setCurrentDirectory(new File("."));  79.         ExtensionFileFilter filter = new ExtensionFileFilter();  80.         filter.addExtension(".zip");  81.         filter.addExtension(".jar");  82.         filter.setDescription("ZIP archives");  83.         chooser.setFileFilter(filter);  84.         int r = chooser.showOpenDialog(ZipTestFrame.this);  85.         if (r == JFileChooser.APPROVE_OPTION)  86.         {  87.            zipname = chooser.getSelectedFile().getPath();  88.            scanZipFile();  89.         }  90.      }  91.   }  92.  93.   /**  94.      Scans the contents of the zip archive and populates  95.      the combo box.  96.   */  97.   public void scanZipFile()  98.   {  99.      fileCombo.removeAllItems(); 100.      try 101.      { 102.         ZipInputStream zin = new ZipInputStream(new FileInputStream(zipname)); 103.         ZipEntry entry; 104.         while ((entry = zin.getNextEntry()) != null) 105.         { 106.            fileCombo.addItem(entry.getName()); 107.            zin.closeEntry(); 108.         } 109.         zin.close(); 110.      } 111.      catch (IOException e) 112.      { 113.         e.printStackTrace(); 114.      } 115.   } 116. 117.   /** 118.      Loads a file from the zip archive into the text area 119.      @param name the name of the file in the archive 120.   */ 121.   public void loadZipFile(String name) 122.   { 123.      try 124.      { 125.         ZipInputStream zin = new ZipInputStream(new FileInputStream(zipname)); 126.         ZipEntry entry; 127.         fileText.setText(""); 128. 129.         // find entry with matching name in archive 130.         while ((entry = zin.getNextEntry()) != null) 131.         { 132.            if (entry.getName().equals(name)) 133.            { 134.               // read entry into text area 135.               BufferedReader in = new BufferedReader(new InputStreamReader(zin)); 136.               String line; 137.               while ((line = in.readLine()) != null) 138.               { 139.                  fileText.append(line); 140.                  fileText.append("\n"); 141.               } 142.            } 143.            zin.closeEntry(); 144.         } 145.         zin.close(); 146.      } 147.      catch (IOException e) 148.      { 149.         e.printStackTrace(); 150.      } 151.   } 152. 153.   public static final int DEFAULT_WIDTH = 400; 154.   public static final int DEFAULT_HEIGHT = 300; 155. 156.   private JComboBox fileCombo; 157.   private JTextArea fileText; 158.   private String zipname; 159. } 160. 161. /** 162.   This file filter matches all files with a given set of 163.   extensions. From FileChooserTest in chapter 9 164. */ 165.class ExtensionFileFilter extends FileFilter 166. { 167.   /** 168.      Adds an extension that this file filter recognizes. 169.      @param extension a file extension (such as ".txt" or "txt") 170.   */ 171.   public void addExtension(String extension) 172.   { 173.      if (!extension.startsWith(".")) 174.         extension = "." + extension; 175.      extensions.add(extension.toLowerCase()); 176.   } 177. 178.   /** 179.      Sets a description for the file set that this file filter 180.      recognizes. 181.      @param aDescription a description for the file set 182.   */ 183.   public void setDescription(String aDescription) 184.   { 185.      description = aDescription; 186.   } 187. 188.   /** 189.      Returns a description for the file set that this file 190.      filter recognizes. 191.      @return a description for the file set 192.   */ 193.   public String getDescription() 194.   { 195.      return description; 196.   } 197. 198.   public boolean accept(File f) 199.   { 200.      if (f.isDirectory()) return true; 201.      String name = f.getName().toLowerCase(); 202. 203.      // check if the file name ends with any of the extensions 204.      for (String e : extensions) 205.         if (name.endsWith(e)) 206.            return true; 207.      return false; 208.   } 209. 210.   private String description = ""; 211.   private ArrayList<String> extensions = new ArrayList<String>(); 212.} 

Figure 12-5. The ZipTest program


NOTE

The ZIP input stream throws a ZipException when there is an error in reading a ZIP file. Normally this error occurs when the ZIP file has been corrupted.


To write a ZIP file, you open a ZipOutputStream by layering it onto a FileOutputStream. For each entry that you want to place into the ZIP file, you create a ZipEntry object. You pass the file name to the ZipEntry constructor; it sets the other parameters such as file date and decompression method automatically. You can override these settings if you like. Then, you call the putNextEntry method of the ZipOutputStream to begin writing a new file. Send the file data to the ZIP stream. When you are done, call closeEntry. Repeat for all the files you want to store. Here is a code skeleton:


FileOutputStream fout = new FileOutputStream("test.zip");
ZipOutputStream zout = new ZipOutputStream(fout);
for all files
{
   ZipEntry ze = new ZipEntry(filename);
   zout.putNextEntry(ze);
   send data to zout;
   zout.closeEntry();
}
zout.close();

NOTE

JAR files (which were discussed in Chapter 10) are simply ZIP files with another entry, the so-called manifest. You use the JarInputStream and JarOutputStream classes to read and write the manifest entry.


ZIP streams are a good example of the power of the stream abstraction. Both the source and the destination of the ZIP data are completely flexible. You layer the most convenient reader stream onto the ZIP file stream to read the data that are stored in compressed form, and that reader doesn't even realize that the data are being decompressed as they are being requested. And the source of the bytes in ZIP formats need not be a file the ZIP data can come from a network connection. In fact, the JAR files that we discussed in Chapter 10 are ZIP-formatted files. Whenever the class loader of an applet reads a JAR file, it reads and decompresses data from the network.

NOTE

The article at http://www.javaworld.com/javaworld/jw-10-2000/jw-1027-toolbox.html shows you how to modify a ZIP archive.



 java.util.zip.ZipInputStream 1.1 

  • ZipInputStream(InputStream in)

    This constructor creates a ZipInputStream that allows you to inflate data from the given InputStream.

    Parameters:

    In

    The underlying input stream


  • ZipEntry getNextEntry()

    returns a ZipEntry object for the next entry, or null if there are no more entries.

  • void closeEntry()

    closes the current open entry in the ZIP file. You can then read the next entry by using getNextEntry().


 java.util.zip.ZipOutputStream 1.1 

  • ZipOutputStream(OutputStream out)

    this constructor creates a ZipOutputStream that you use to write compressed data to the specified OutputStream.

    Parameters:

    Out

    The underlying output stream


  • void putNextEntry(ZipEntry ze)

    writes the information in the given ZipEntry to the stream and positions the stream for the data. The data can then be written to the stream by write().

    Parameters:

    ze

    The new entry


  • void closeEntry()

    closes the currently open entry in the ZIP file. Use the putNextEntry method to start the next entry.

  • void setLevel(int level)

    sets the default compression level of subsequent DEFLATED entries. The default value is Deflater.DEFAULT_COMPRESSION. Throws an IllegalArgumentException if the level is not valid.

    Parameters:

    level

    A compression level, from 0 (NO_COMPRESSION) to 9 (BEST_COMPRESSION)


  • void setMethod(int method)

    sets the default compression method for this ZipOutputStream for any entries that do not specify a method.

    Parameters:

    method

    The compression method, either DEFLATED or STORED



 java.util.zip.ZipEntry 1.1 

  • ZipEntry(String name)

    Parameters:

    name

    The name of the entry


  • long getCrc()

    returns the CRC32 checksum value for this ZipEntry.

  • String getName()

    returns the name of this entry.

  • long getSize()

    returns the uncompressed size of this entry, or 1 if the uncompressed size is not known.

  • boolean isDirectory()

    returns a Boolean that indicates whether this entry is a directory.

  • void setMethod(int method)

    Parameters:

    method

    The compression method for the entry; must be either DEFLATED or STORED


  • void setSize(long size)

    sets the size of this entry. Only required if the compression method is STORED.

    Parameters:

    size

    The uncompressed size of this entry


  • void setCrc(long crc)

    sets the CRC32 checksum of this entry. Use the CRC32 class to compute this checksum. Only required if the compression method is STORED.

    Parameters:

    crc

    The checksum of this entry



 java.util.zip.ZipFile 1.1 

  • ZipFile(String name)

    this constructor creates a ZipFile for reading from the given string.

    Parameters:

    name

    A string that contains the path name of the file


  • ZipFile(File file)

    this constructor creates a ZipFile for reading from the given File object.

    Parameters:

    file

    The file to read; the File class is described at the end of this chapter


  • Enumeration entries()

    returns an Enumeration object that enumerates the ZipEntry objects that describe the entries of the ZipFile.

  • ZipEntry getEntry(String name)

    returns the entry corresponding to the given name, or null if there is no such entry.

    Parameters:

    name

    The entry name


  • InputStream getInputStream(ZipEntry ze)

    returns an InputStream for the given entry.

    Parameters:

    ze

    A ZipEntry in the ZIP file


  • String getName()

    returns the path of this ZIP file.


       
    top



    Core Java 2 Volume I - Fundamentals
    Core Java(TM) 2, Volume I--Fundamentals (7th Edition) (Core Series) (Core Series)
    ISBN: 0131482025
    EAN: 2147483647
    Year: 2003
    Pages: 132

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net