zip扮演着归档和压缩两个角色;gzip并不将文件归档,仅只是对单个文件进行压缩,所以,在UNIX平台上,命令tar通常用来创建一个档案文件,然后命令gzip来将档案文件压缩。

Java I/O类库还收录了一些能读写压缩格式流的类。要想提供压缩功能,只要把它们包在已有的I/O类的外面就行了。这些类不是Reader和Writer,而是InputStream和OutStreamput的子类。这是因为压缩算法是针对byte而不是字符的。

相关类与接口:
Checksum接口:被类Adler32和CRC32实现的接口
Adler32:使用Alder32算法来计算Checksum数目
CRC32:使用CRC32算法来计算Checksum数目

CheckedInputStream:InputStream派生类,可得到输入流的校验和Checksum,用于校验数据的完整性
CheckedOutputStream:OutputStream派生类,可得到输出流的校验和Checksum,用于校验数据的完整性

DeflaterOutputStream:压缩类的基类。
ZipOutputStream:DeflaterOutputStream的一个子类,把数据压缩成Zip文件格式。
GZIPOutputStream:DeflaterOutputStream的一个子类,把数据压缩成GZip文件格式

InflaterInputStream:解压缩类的基类
ZipInputStream:InflaterInputStream的一个子类,能解压缩Zip格式的数据
GZIPInputStream:InflaterInputStream的一个子类,能解压缩Zip格式的数据

ZipEntry类:表示 ZIP 文件条目
ZipFile类:此类用于从 ZIP 文件读取条目

用GZIP进行对单个文件压缩

GZIP的接口比较简单,因此如果你只需对一个流进行压缩的话,可以使用它。当然它可以压缩字符流,与可以压缩字节流,下面是一个对GBK编码格式的文本文件进行压缩的。
压缩类的用法非常简单;只要用GZIPOutputStream 或ZipOutputStream把输出流包起来,再用GZIPInputStream 或ZipInputStream把输入流包起来就行了。剩下的都是些普通的I/O操作。

1. package
2.   
3. import
4. import
5. import
6. import
7. import
8. import
9. import
10. import
11. import
12. import
13. import
14. import
15. import
16. import
17. import
18. import
19. import
20.   
21. /** 利用apache提供的ant.jar,提供对单个文件与目录的压缩,并支持是否需要创建压缩源目录、中文路径
22.  * @Title:
23.  * @Description:ZipCompress
24.  * @Version 1.2
25.  */
26. public class
27.   
28. private static boolean isCreateSrcDir = true;//是否创建源目录 
29.   
30. /**
31.      * @param args
32.      * @throws IOException
33.      */
34. public static void main(String[] args) throws
35. "f:\\中文包";//指定压缩源,可以是目录或文件 
36. "f:\\depress";//解压路径 
37. "f:\\中文压缩文件.zip";//压缩包路径 
38. "Java Zip 测试.";//压缩包注释 
39. //----压缩文件或目录 
40.         writeByApacheZipOutputStream(src,archive,comment);  
41. /*
42.          * 读压缩文件,注释掉,因为使用的是apache的压缩类,所以使用java类库中
43.          * 解压类时出错,这里不能运行
44.          */
45.         readByZipInputStream(archive, decompressDir);  
46. //----使用apace ZipFile读取压缩文件 
47.         readByApacheZipFile(archive, decompressDir);  
48.     }  
49. /**对文件夹或者文件进行压缩
50.      * 
51.      * @Time 2012-3-9 上午09:32:35 create
52.      * @param src
53.      * @param archive
54.      * @param comment
55.      * @throws FileNotFoundException
56.      * @throws IOException
57.      * @author jiangzhenming
58.      */
59. public static void
60. throws
61. //----压缩文件: 
62. new
63. //使用指定校验和创建输出流 
64. new CheckedOutputStream(f, new
65.   
66. new
67. //支持中文 
68. "GBK");  
69. new
70. //设置压缩包注释 
71.         zos.setComment(comment);  
72. //启用压缩 
73.         zos.setMethod(ZipOutputStream.DEFLATED);  
74. //压缩级别为最强压缩,但时间要花得多一点 
75.         zos.setLevel(Deflater.BEST_COMPRESSION);  
76.   
77. new
78.   
79. if (!srcFile.exists() || (srcFile.isDirectory() && srcFile.list().length == 0)) {  
80. throw new
81. "File must exist and  ZIP file must have at least one entry.");  
82.         }  
83. //获取压缩源所在父目录 
84. "\\\\", "/");  
85. null;  
86. if
87. 0, src.lastIndexOf("/") + 1);  
88. else
89. "/$", "") + "/");  
90.         }  
91.   
92. //如果不是根目录 
93. if (prefixDir.indexOf("/") != (prefixDir.length() - 1) && isCreateSrcDir) {  
94. "[^/]+/$", "");  
95.         }  
96.   
97. //开始压缩 
98.         writeRecursive(zos, out, srcFile, prefixDir);  
99.   
100.         out.close();  
101. // 注:校验和要在流关闭后才准备,一定要放在流被关闭后使用 
102. "Checksum: "
103.         BufferedInputStream bi;  
104.     }  
105.   
106. /**
107.      * 使用 org.apache.tools.zip.ZipFile 解压文件,它与 java 类库中的
108.      * java.util.zip.ZipFile 使用方式是一新的,只不过多了设置编码方式的
109.      * 接口。
110.      * 
111.      * 注,apache 没有提供 ZipInputStream 类,所以只能使用它提供的ZipFile
112.      * 来读取压缩文件。
113.      * @param archive 压缩包路径
114.      * @param decompressDir 解压路径
115.      * @throws IOException
116.      * @throws FileNotFoundException
117.      * @throws ZipException
118.      */
119. public static void
120. throws
121.         BufferedInputStream bi;  
122.   
123. new ZipFile(archive, "GBK");//支持中文 
124.   
125.         Enumeration e = zf.getEntries();  
126. while
127.             ZipEntry ze2 = (ZipEntry) e.nextElement();  
128.             String entryName = ze2.getName();  
129. "/"
130. if
131. "正在创建解压目录 - "
132. new
133. if
134.                     decompressDirFile.mkdirs();  
135.                 }  
136. else
137. "正在创建解压文件 - "
138. 0, path.lastIndexOf("/"));  
139. new
140. if
141.                     fileDirFile.mkdirs();  
142.                 }  
143. new BufferedOutputStream(new
144. "/"
145.   
146. new
147. byte[] readContent = new byte[1024];  
148. int
149. while (readCount != -1) {  
150. 0, readCount);  
151.                     readCount = bi.read(readContent);  
152.                 }  
153.                 bos.close();  
154.             }  
155.         }  
156.         zf.close();  
157.     }  
158.   
159. /**
160.      * 使用 java api 中的 ZipInputStream 类解压文件,但如果压缩时采用了
161.      * org.apache.tools.zip.ZipOutputStream时,而不是 java 类库中的
162.      * java.util.zip.ZipOutputStream时,该方法不能使用,原因就是编码方
163.      * 式不一致导致,运行时会抛如下异常:
164.      * java.lang.IllegalArgumentException
165.      * at java.util.zip.ZipInputStream.getUTF8String(ZipInputStream.java:290)
166.      * 
167.      * 当然,如果压缩包使用的是java类库的java.util.zip.ZipOutputStream
168.      * 压缩而成是不会有问题的,但它不支持中文
169.      * 
170.      * @param archive 压缩包路径
171.      * @param decompressDir 解压路径
172.      * @throws FileNotFoundException
173.      * @throws IOException
174.      */
175. public static void
176. throws
177.         BufferedInputStream bi;  
178. //----解压文件(ZIP文件的解压缩实质上就是从输入流中读取数据): 
179. "开始读压缩文件");  
180.   
181. new
182. new CheckedInputStream(fi, new
183. new
184. new
185. //压缩文件条目 
186. //遍历压缩包中的文件条目 
187. while ((ze = in2.getNextEntry()) != null) {  
188.             String entryName = ze.getName();  
189. if
190. "正在创建解压目录 - "
191. new File(decompressDir + "/"
192. if
193.                     decompressDirFile.mkdirs();  
194.                 }  
195. else
196. "正在创建解压文件 - "
197. new BufferedOutputStream(new
198. "/"
199. byte[] buffer = new byte[1024];  
200. int
201.   
202. while (readCount != -1) {  
203. 0, readCount);  
204.                     readCount = bi.read(buffer);  
205.                 }  
206.                 bos.close();  
207.             }  
208.         }  
209.         bi.close();  
210. "Checksum: "
211.     }  
212.   
213. /**
214.      * 递归压缩
215.      * 
216.      * 使用 org.apache.tools.zip.ZipOutputStream 类进行压缩,它的好处就是支持中文路径,
217.      * 而Java类库中的 java.util.zip.ZipOutputStream 压缩中文文件名时压缩包会出现乱码。
218.      * 使用 apache 中的这个类与 java 类库中的用法是一新的,只是能设置编码方式了。
219.      *  
220.      * @param zos
221.      * @param bo
222.      * @param srcFile
223.      * @param prefixDir
224.      * @throws IOException
225.      * @throws FileNotFoundException
226.      */
227. private static void
228. throws
229.         ZipEntry zipEntry;  
230.   
231. "\\\\", "/").replaceAll(  
232. "//", "/");  
233. if
234. "/$", "") + "/";  
235.         }  
236. "").replaceAll("/$", "");  
237. if
238. if (!"".equals(entryName)) {  
239. "正在创建目录 - "
240. "  entryName="
241.   
242. //如果是目录,则需要在写目录后面加上 /  
243. new ZipEntry(entryName + "/");  
244.                 zos.putNextEntry(zipEntry);  
245.             }  
246.   
247.             File srcFiles[] = srcFile.listFiles();  
248. for (int i = 0; i < srcFiles.length; i++) {  
249.                 writeRecursive(zos, bo, srcFiles[i], prefixDir);  
250.             }  
251. else
252. "正在写文件 - " + srcFile.getAbsolutePath() + "  entryName="
253.                     + entryName);  
254. new BufferedInputStream(new
255.   
256. //开始写入新的ZIP文件条目并将流定位到条目数据的开始处 
257. new
258.             zos.putNextEntry(zipEntry);  
259. byte[] buffer = new byte[1024];  
260. int
261.   
262. while (readCount != -1) {  
263. 0, readCount);  
264.                 readCount = bi.read(buffer);  
265.             }  
266. //注,在使用缓冲流写压缩文件时,一个条件完后一定要刷新一把,不 
267. //然可能有的内容就会存入到后面条目中去了 
268.             bo.flush();  
269. //文件读完后关闭 
270.             bi.close();  
271.         }  
272.     }  
273. }