Java ScreenShot
Screenshot      

Screenshot Core Java 2: Volume I - Fundamentals

Table of Contents
 12.  Streams and Files


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.)

Java graphics notes_icon.gif

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 list box at the top 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 Screenshot-4.

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.show();
 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. Container contentPane = getContentPane();
 66. contentPane.add(fileCombo, BorderLayout.SOUTH);
 67. contentPane.add(fileText, BorderLayout.CENTER);
 68. }
 69.
 70. /**
 71. This is the listener for the File->Open menu item.
 72. */
 73. private class OpenAction implements ActionListener
 74. {
 75. public void actionPerformed(ActionEvent evt)
 76. {
 77. // prompt the user for a zip file
 78. JFileChooser chooser = new JFileChooser();
 79. chooser.setCurrentDirectory(new File("."));
 80. ExtensionFileFilter filter = new ExtensionFileFilter();
 81. filter.addExtension(".zip");
 82. filter.addExtension(".jar");
 83. filter.setDescription("ZIP archives");
 84. chooser.setFileFilter(filter);
 85. int r = chooser.showOpenDialog(ZipTestFrame.this);
 86. if (r == JFileChooser.APPROVE_OPTION)
 87. {
 88. zipname = chooser.getSelectedFile().getPath();
 89. scanZipFile();
 90. }
 91. }
 92. }
 93.
 94. /**
 95. Scans the contents of the zip archive and populates
 96. the combo box.
 97. */
 98. public void scanZipFile()
 99. {
100. fileCombo.removeAllItems();
101. try
102. {
103. ZipInputStream zin = new ZipInputStream(new
104. FileInputStream(zipname));
105. ZipEntry entry;
106. while ((entry = zin.getNextEntry()) != null)
107. {
108. fileCombo.addItem(entry.getName());
109. zin.closeEntry();
110. }
111. zin.close();
112. }
113. catch (IOException e)
114. {
115. e.printStackTrace();
116. }
117. }
118.
119. /**
120. Loads a file from the zip archive into the text area
121. @param name the name of the file in the archive
122. */
123. public void loadZipFile(String name)
124. {
125. try
126. {
127. ZipInputStream zin = new ZipInputStream(new
128. FileInputStream(zipname));
129. ZipEntry entry;
130. fileText.setText("");
131.
132. // find entry with matching name in archive
133. while ((entry = zin.getNextEntry()) != null)
134. {
135. if (entry.getName().equals(name))
136. {
137. // read entry into text area
138. BufferedReader in = new BufferedReader(new
139. InputStreamReader(zin));
140. String line;
141. while ((line = in.readLine()) != null)
142. {
143. fileText.append(line);
144. fileText.append("\n");
145. }
146. }
147. zin.closeEntry();
148. }
149. zin.close();
150. }
151. catch (IOException e)
152. {
153. e.printStackTrace();
154. }
155. }
156.
157. public static final int DEFAULT_WIDTH = 400;
158. public static final int DEFAULT_HEIGHT = 300;
159.
160. private JComboBox fileCombo;
161. private JTextArea fileText;
162. private String zipname;
163. }
164.
165. /**
166. This file filter matches all files with a given set of
167. extensions. From FileChooserTest in chapter 9
168. */
169. class ExtensionFileFilter extends FileFilter
170. {
171. /**
172. Adds an extension that this file filter recognizes.
173. @param extension a file extension (such as ".txt" or "txt")
174. */
175. public void addExtension(String extension)
176. {
177. if (!extension.startsWith("."))
178. extension = "." + extension;
179. extensions.add(extension.toLowerCase());
180. }
181.
182. /**
183. Sets a description for the file set that this file filter
184. recognizes.
185. @param aDescription a description for the file set
186. */
187. public void setDescription(String aDescription)
188. {
189. description = aDescription;
190. }
191.
192. /**
193. Returns a description for the file set that this file
194. filter recognizes.
195. @return a description for the file set
196. */
197. public String getDescription()
198. {
199. return description;
200. }
201.
202. public boolean accept(File f)
203. {
204. if (f.isDirectory()) return true;
205. String name = f.getName().toLowerCase();
206.
207. // check if the file name ends with any of the extensions
208. for (int i = 0; i < extensions.size(); i++)
209. if (name.endsWith((String)extensions.get(i)))
210. return true;
211. return false;
212. }
213.
214. private String description = "";
215. private ArrayList extensions = new ArrayList();
216. }


Screenshot-4. The ZipTest program

Java graphics 12fig04.gif


Java graphics notes_icon.gif

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 is 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(file name);
 zout.putNextEntry(ze);
 send data to zout;
 zout.closeEntry();
}
zout.close();


Java graphics notes_icon.gif

JAR files (which were discussed in ) 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 is stored in compressed form, and that reader doesn't even realize that the data is being decompressed as it is 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 are ZIP-formatted files. Whenever the class loader of an applet reads a JAR file, it reads and decompresses data from the network.
Java graphics notes_icon.gif

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

Java graphics api_icon.gif
  • 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

Java graphics api_icon.gif
  • 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

Java graphics api_icon.gif
  • 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 or not 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

Java graphics api_icon.gif
  • 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.


Java ScreenShot
Screenshot      
Top
 

Comments