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

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

Example 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. }

The ZipTest program

Java graphics 12fig04Java graphics notes_icon

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

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

The article at shows you how to modify a ZIP archive.

java.util.zip.ZipInputStream 1.1

Java graphics api_icon