闲言少叙,先说ZIP压缩。
zip压缩需要通过ZipOutputStream 执行write方法将压缩数据写到指定输出流中。
注意,这里应先使用CheckedOutputStream 指定文件校验算法。(通常使用CRC32算法)。代码如下所示:
Java代码
1. CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(destPath), new
2. ZipOutputStream zos = new
接下来,需要将待压缩文件以ZipEntry的方式追加到压缩文件中,如下所示:
1. /**
2. * 压缩包内文件名定义
3. *
4. * <pre>
5. * 如果有多级目录,那么这里就需要给出包含目录的文件名
6. * 如果用WinRAR打开压缩包,中文名将显示为乱码
7. * </pre>
8. */
9. ZipEntry entry = new
10.
11. zos.putNextEntry(entry);
ZipEntry就是压缩包中的每一个实体!
完成上述准备后,就可以执行压缩操作了。实际上,就是执行ZipOutputStream类的write方法,如下所示:
Java代码
1. BufferedInputStream bis = new BufferedInputStream(new
2. file));
3.
4. int
5. byte data[] = new byte[BUFFER];
6. while ((count = bis.read(data, 0, BUFFER)) != -1) {
7. 0, count);
8. }
9. bis.close();
当然,如果待添加的压缩项是一个目录。那么,需要通过递归的方式指定最终的压缩项。
如果要添加一个空目录,注意使用符号"/"(String PATH="/";)作为添加项名字结尾符!
递归构建目录压缩,代码如下:
Java代码
1. /**
2. * 压缩
3. *
4. * @param srcFile
5. * 源路径
6. * @param zos
7. * ZipOutputStream
8. * @param basePath
9. * 压缩包内相对路径
10. * @throws Exception
11. */
12. private static void
13. throws
14. if
15. compressDir(srcFile, zos, basePath);
16. else
17. compressFile(srcFile, zos, basePath);
18. }
19. }
20.
21. /**
22. * 压缩目录
23. *
24. * @param dir
25. * @param zos
26. * @param basePath
27. * @throws Exception
28. */
29. private static void
30. throws
31.
32. File[] files = dir.listFiles();
33.
34. // 构建空目录
35. if (files.length < 1) {
36. new
37.
38. zos.putNextEntry(entry);
39. zos.closeEntry();
40. }
41.
42. for
43. // 递归压缩
44. compress(file, zos, basePath + dir.getName() + PATH);
45. }
46. }
x是一个空目录,用WinRAR打开后,可以看到这个目录下还有一个空文件名文件!
来个完整的压缩实现,代码如下所示:
Java代码
1. /**
2. * 2010-4-12
3. */
4. package
5.
6. import
7. import
8. import
9. import
10. import
11. import
12. import
13. import
14. import
15. import
16. import
17.
18. /**
19. * ZIP压缩工具
20. *
21. * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a>
22. * @since 1.0
23. */
24. public class
25.
26. public static final String EXT = ".zip";
27. private static final String BASE_DIR = "";
28.
29. // 符号"/"用来作为目录标识判断符
30. private static final String PATH = "/";
31. private static final int BUFFER = 1024;
32.
33. /**
34. * 压缩
35. *
36. * @param srcFile
37. * @throws Exception
38. */
39. public static void compress(File srcFile) throws
40. String name = srcFile.getName();
41. String basePath = srcFile.getParent();
42. String destPath = basePath + name + EXT;
43. compress(srcFile, destPath);
44. }
45.
46. /**
47. * 压缩
48. *
49. * @param srcFile
50. * 源路径
51. * @param destPath
52. * 目标路径
53. * @throws Exception
54. */
55. public static void compress(File srcFile, File destFile) throws
56.
57. // 对输出文件做CRC32校验
58. new CheckedOutputStream(new
59. new
60.
61. new
62.
63. compress(srcFile, zos, BASE_DIR);
64.
65. zos.flush();
66. zos.close();
67. }
68.
69. /**
70. * 压缩文件
71. *
72. * @param srcFile
73. * @param destPath
74. * @throws Exception
75. */
76. public static void compress(File srcFile, String destPath) throws
77. new
78. }
79.
80. /**
81. * 压缩
82. *
83. * @param srcFile
84. * 源路径
85. * @param zos
86. * ZipOutputStream
87. * @param basePath
88. * 压缩包内相对路径
89. * @throws Exception
90. */
91. private static void
92. throws
93. if
94. compressDir(srcFile, zos, basePath);
95. else
96. compressFile(srcFile, zos, basePath);
97. }
98. }
99.
100. /**
101. * 压缩
102. *
103. * @param srcPath
104. * @throws Exception
105. */
106. public static void compress(String srcPath) throws
107. new
108.
109. compress(srcFile);
110. }
111.
112. /**
113. * 文件压缩
114. *
115. * @param srcPath
116. * 源文件路径
117. * @param destPath
118. * 目标文件路径
119. *
120. */
121. public static void
122. throws
123. new
124.
125. compress(srcFile, destPath);
126. }
127.
128. /**
129. * 压缩目录
130. *
131. * @param dir
132. * @param zos
133. * @param basePath
134. * @throws Exception
135. */
136. private static void
137. throws
138.
139. File[] files = dir.listFiles();
140.
141. // 构建空目录
142. if (files.length < 1) {
143. new
144.
145. zos.putNextEntry(entry);
146. zos.closeEntry();
147. }
148.
149. for
150.
151. // 递归压缩
152. compress(file, zos, basePath + dir.getName() + PATH);
153.
154. }
155. }
156.
157. /**
158. * 文件压缩
159. *
160. * @param file
161. * 待压缩文件
162. * @param zos
163. * ZipOutputStream
164. * @param dir
165. * 压缩文件中的当前路径
166. * @throws Exception
167. */
168. private static void
169. throws
170.
171. /**
172. * 压缩包内文件名定义
173. *
174. * <pre>
175. * 如果有多级目录,那么这里就需要给出包含目录的文件名
176. * 如果用WinRAR打开压缩包,中文名将显示为乱码
177. * </pre>
178. */
179. new
180.
181. zos.putNextEntry(entry);
182.
183. new BufferedInputStream(new
184. file));
185.
186. int
187. byte data[] = new byte[BUFFER];
188. while ((count = bis.read(data, 0, BUFFER)) != -1) {
189. 0, count);
190. }
191. bis.close();
192.
193. zos.closeEntry();
194. }
195.
196. }
来做个简单的测试:
Java代码
1. import static
2.
3. import
4.
5. /**
6. *
7. * @author 梁栋
8. * @version 1.0
9. * @since 1.0
10. */
11. public class
12.
13. /**
14. *
15. */
16. @Test
17. public void test() throws
18. // 压缩文件
19. "d:\\f.txt");
20. // 压缩目录
21. "d:\\fd");
22. }
23. }
现在用WinRAR打开看看,是不是效果几乎一致?
当然,上述代码有所不足之处主要是中文名称乱码问题。用java原生ZIP实现压缩后得到的压缩包,与系统的字符集不同,文件/目录名将出现乱码。这是所有归档压缩都会遇到的问题。对于这种问题,Commons Copress提供了解决方案!