ZipUtils.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. /**
  2. *
  3. * Copyright (c) behosoft Co.,Ltd.
  4. * All Rights Reserved.
  5. *
  6. * This software is the confidential and proprietary information of behosoft.
  7. * (Social Security Department). You shall not disclose such
  8. * Confidential Information and shall use it only in accordance with
  9. * the terms of the license agreement you entered into with behosoft.
  10. *
  11. * Distributable under GNU LGPL license by gnu.org
  12. */
  13. package com.behosoft.util;
  14. import java.io.BufferedInputStream;
  15. import java.io.File;
  16. import java.io.FileInputStream;
  17. import java.io.FileOutputStream;
  18. import java.io.InputStream;
  19. import java.io.OutputStream;
  20. import java.util.ArrayList;
  21. import java.util.Enumeration;
  22. import java.util.List;
  23. import java.util.zip.CRC32;
  24. import java.util.zip.CheckedOutputStream;
  25. import org.apache.tools.zip.ZipEntry;
  26. import org.apache.tools.zip.ZipFile;
  27. import org.apache.tools.zip.ZipOutputStream;
  28. /**
  29. * <p>
  30. * Title: behosoft_[子系统统名]_[模块名]
  31. * </p>
  32. * <p>
  33. * Description: zip文件的压缩和解压
  34. * </p>
  35. *
  36. * @author 蒋勇华
  37. * @version $Revision$ 2013-6-19
  38. * @author (lastest modification by $Author$)
  39. * @since 1.0
  40. */
  41. public class ZipUtils {
  42. public static final String EXT = ".zip";
  43. private static final String ENCODE = "gbk";
  44. private static final String BASE_DIR = "";
  45. private static final String PATH = File.separator;// 符号"/"用来作为目录标识判断符
  46. private static final int BUFFER = 8192;
  47. private static final long MAX_FILE_SIZE = 1610612736;// 单个压缩文件的最大大小 1.5G
  48. private static String getShortName(String fileName) {
  49. int index = fileName.indexOf(".");
  50. if (index > -1) {
  51. fileName = fileName.substring(0, index);
  52. }
  53. return fileName;
  54. }
  55. /**
  56. * 压缩
  57. *
  58. * @param srcFile
  59. * @throws Exception
  60. */
  61. public static void compress(File srcFile) throws Exception {
  62. String name = getShortName(srcFile.getName());
  63. String basePath = srcFile.getParent() + PATH;
  64. String destPath = basePath + name + EXT;
  65. compress(srcFile, destPath);
  66. }
  67. /**
  68. * 压缩单个文件或目录
  69. *
  70. * @param srcFile 源路径
  71. * @param destPath 目标路径
  72. * @throws Exception
  73. */
  74. public static void compress(File srcFile, File destFile) throws Exception {
  75. // 对输出文件做CRC32校验
  76. CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(destFile), new CRC32());
  77. ZipOutputStream zos = new ZipOutputStream(cos);
  78. zos.setEncoding(ENCODE);
  79. compress(srcFile, zos, BASE_DIR);
  80. zos.flush();
  81. zos.close();
  82. }
  83. /***
  84. * <p>
  85. * Description:压缩多个文件或目录
  86. * </p>
  87. *
  88. * @param srcFiles
  89. * @param destFile
  90. * @throws Exception
  91. */
  92. public static void compress(File[] srcFiles, File destFile) throws Exception {
  93. // 对输出文件做CRC32校验
  94. CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(destFile), new CRC32());
  95. ZipOutputStream zos = new ZipOutputStream(cos);
  96. zos.setEncoding(ENCODE);
  97. for (File srcFile : srcFiles) {
  98. compress(srcFile, zos, BASE_DIR);
  99. }
  100. zos.flush();
  101. zos.close();
  102. }
  103. /**
  104. * 压缩文件
  105. *
  106. * @param srcFile
  107. * @param destPath
  108. * @throws Exception
  109. */
  110. public static void compress(File srcFile, String destPath) throws Exception {
  111. compress(srcFile, new File(destPath));
  112. }
  113. /**
  114. * 压缩
  115. *
  116. * @param srcFile 源路径
  117. * @param zos ZipOutputStream
  118. * @param basePath 压缩包内相对路径
  119. * @throws Exception
  120. */
  121. private static void compress(File srcFile, ZipOutputStream zos, String basePath) throws Exception {
  122. if (srcFile.isDirectory()) {
  123. compressDir(srcFile, zos, basePath);
  124. }
  125. else {
  126. compressFile(srcFile, zos, basePath);
  127. }
  128. }
  129. /**
  130. * 压缩
  131. *
  132. * @param srcPath
  133. * @throws Exception
  134. */
  135. public static void compress(String srcPath) throws Exception {
  136. File srcFile = new File(srcPath);
  137. compress(srcFile);
  138. }
  139. /**
  140. * 文件压缩
  141. *
  142. * @param srcPath 源文件路径
  143. * @param destPath 目标文件路径
  144. */
  145. public static void compress(String srcPath, String destPath) throws Exception {
  146. File srcFile = new File(srcPath);
  147. compress(srcFile, destPath);
  148. }
  149. /**
  150. * 压缩目录
  151. *
  152. * @param dir
  153. * @param zos
  154. * @param basePath
  155. * @throws Exception
  156. */
  157. private static void compressDir(File dir, ZipOutputStream zos, String basePath) throws Exception {
  158. File[] files = dir.listFiles();
  159. // 构建空目录
  160. if (files.length < 1) {
  161. ZipEntry entry = new ZipEntry(basePath + dir.getName() + PATH);
  162. zos.putNextEntry(entry);
  163. zos.closeEntry();
  164. }
  165. for (File file : files) {
  166. // 递归压缩
  167. compress(file, zos, basePath + dir.getName() + PATH);
  168. }
  169. }
  170. /**
  171. * 文件压缩
  172. *
  173. * @param file 待压缩文件
  174. * @param zos ZipOutputStream
  175. * @param dir 压缩文件中的当前路径
  176. * @throws Exception
  177. */
  178. private static void compressFile(File file, ZipOutputStream zos, String dir) throws Exception {
  179. /**
  180. * 压缩包内文件名定义
  181. *
  182. * <pre>
  183. * 如果有多级目录,那么这里就需要给出包含目录的文件名
  184. * 如果用WinRAR打开压缩包,中文名将显示为乱码
  185. * </pre>
  186. */
  187. ZipEntry entry = new ZipEntry(dir + file.getName());
  188. zos.putNextEntry(entry);
  189. BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
  190. int count;
  191. byte data[] = new byte[BUFFER];
  192. while ((count = bis.read(data, 0, BUFFER)) != -1) {
  193. zos.write(data, 0, count);
  194. }
  195. bis.close();
  196. zos.closeEntry();
  197. }
  198. private static File createCompressedDir(File sourceDir, File destDir) {
  199. File archiveDir = new File(destDir.getAbsolutePath() + File.separator + sourceDir.getName());
  200. if (!archiveDir.exists()) {
  201. archiveDir.mkdir();
  202. }
  203. return archiveDir;
  204. }
  205. /***
  206. * 分卷压缩目录
  207. *
  208. * @param sourcePath 源目录
  209. * @param destPath 压缩完成后放置到的目录
  210. * @return
  211. * @throws Exception
  212. */
  213. public static File volumeCompressDir(String sourcePath, String destPath) throws Exception {
  214. File sourceDir = new File(sourcePath);
  215. File destDir = new File(destPath);
  216. return volumeCompressDir(sourceDir, destDir);
  217. }
  218. /***
  219. * 分卷压缩目录
  220. *
  221. * @param sourceDir 源目录
  222. * @param destDir 压缩完成后放置到的目录
  223. * @return
  224. * @throws Exception
  225. */
  226. public static File volumeCompressDir(File sourceDir, File destDir) throws Exception {
  227. if (!sourceDir.isDirectory()) {
  228. throw new Exception("源路径不是有效的目录");
  229. }
  230. if (!destDir.isDirectory()) {
  231. throw new Exception("目标路径不是有效的目录");
  232. }
  233. File compressedDir = createCompressedDir(sourceDir, destDir);
  234. String basePath = compressedDir.getAbsolutePath() + File.separator;
  235. File[] list = sourceDir.listFiles();
  236. long compressedSize = 0;
  237. int volumeCount = 1;
  238. ZipOutputStream zos = null;
  239. for (File file : list) {
  240. if (file.isFile()) {
  241. if (zos == null) {
  242. CheckedOutputStream cos =
  243. new CheckedOutputStream(new FileOutputStream(basePath + sourceDir.getName() + "_"
  244. + volumeCount + EXT), new CRC32());
  245. zos = new ZipOutputStream(cos);
  246. zos.setEncoding(ENCODE);
  247. compressedSize = addVolumeCompressFile(file, zos).getSize();
  248. }
  249. else {
  250. if ((compressedSize + file.length()) >= MAX_FILE_SIZE) {
  251. if (zos != null) {
  252. zos.close();
  253. }
  254. compressedSize = 0;
  255. volumeCount = volumeCount + 1;
  256. CheckedOutputStream cos2 =
  257. new CheckedOutputStream(new FileOutputStream(basePath + sourceDir.getName() + "_"
  258. + volumeCount + EXT), new CRC32());
  259. zos = new ZipOutputStream(cos2);
  260. zos.setEncoding(ENCODE);
  261. compressedSize = compressedSize + addVolumeCompressFile(file, zos).getSize();
  262. }
  263. else {
  264. compressedSize = compressedSize + addVolumeCompressFile(file, zos).getSize();
  265. }
  266. }
  267. }
  268. else {
  269. // 不支持对子目录的压缩
  270. }
  271. }
  272. if (zos != null) {
  273. zos.close();
  274. }
  275. return compressedDir;
  276. }
  277. private static ZipEntry addVolumeCompressFile(File file, ZipOutputStream zos) throws Exception {
  278. ZipEntry entry = new ZipEntry(file.getName());
  279. zos.putNextEntry(entry);
  280. BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
  281. int count;
  282. byte data[] = new byte[BUFFER];
  283. while ((count = bis.read(data, 0, BUFFER)) != -1) {
  284. zos.write(data, 0, count);
  285. zos.flush();
  286. }
  287. bis.close();
  288. zos.closeEntry();
  289. return entry;
  290. }
  291. /***
  292. * 分卷解压缩
  293. *
  294. * @param sourcePath
  295. * @param destPath
  296. * @return
  297. * @throws Exception
  298. */
  299. public static List<String> unCompressVolumeDir(String sourcePath, String destPath) throws Exception {
  300. File sourceDir = new File(sourcePath);
  301. File destDir = new File(destPath);
  302. return unCompressVolumeDir(sourceDir, destDir);
  303. }
  304. /***
  305. * 分卷解压缩
  306. *
  307. * @param sourceDir
  308. * @param destDir
  309. * @return
  310. * @throws Exception
  311. */
  312. public static List<String> unCompressVolumeDir(File sourceDir, File destDir) throws Exception {
  313. if (sourceDir.isFile()) {// 对zip文件的解压
  314. return uncompress(sourceDir.getAbsolutePath(), destDir.getAbsolutePath());
  315. }
  316. else {// 对zip分卷目录的解压
  317. List<String> filePaths = new ArrayList<String>();
  318. if (!sourceDir.isDirectory()) {
  319. throw new Exception("源路径不是有效的目录");
  320. }
  321. if (!destDir.isDirectory()) {
  322. throw new Exception("目标路径不是有效的目录");
  323. }
  324. File[] list = sourceDir.listFiles();
  325. for (File zipFile : list) {
  326. List<String> entries = uncompress(zipFile.getAbsolutePath(), destDir.getAbsolutePath());
  327. for (String s : entries) {
  328. filePaths.add(s);
  329. }
  330. }
  331. return filePaths;
  332. }
  333. }
  334. /***
  335. * 解开单个压缩文件
  336. *
  337. * @param zipFilePath
  338. * @param targetDir
  339. * @return
  340. * @throws Exception
  341. */
  342. public static List<String> uncompress(String zipFilePath, String targetDir) throws Exception {
  343. List<String> list = new ArrayList<String>();
  344. byte b[] = new byte[BUFFER];
  345. if (!targetDir.endsWith(File.separator)) {
  346. targetDir = targetDir + File.separator;
  347. }
  348. ZipFile zipFile = new ZipFile(zipFilePath, ENCODE);
  349. Enumeration<ZipEntry> entries = zipFile.getEntries();
  350. while (entries.hasMoreElements()) {
  351. ZipEntry zipEntry = entries.nextElement();
  352. String fileName = zipEntry.getName();
  353. File targetFolder = new File(targetDir);
  354. if (!targetFolder.exists()) {
  355. targetFolder.mkdir();
  356. }
  357. File temp = new File(targetDir + fileName);
  358. OutputStream os = new FileOutputStream(temp);
  359. // 通过ZipFile的getInputStream方法拿到具体的ZipEntry的输入流
  360. InputStream is = zipFile.getInputStream(zipEntry);
  361. int len = 0;
  362. while ((len = is.read(b)) != -1) {
  363. os.write(b, 0, len);
  364. }
  365. os.close();
  366. is.close();
  367. list.add(targetDir + fileName);
  368. }
  369. return list;
  370. }
  371. /***
  372. * <p>
  373. * Description:解压
  374. * </p>
  375. *
  376. * @param zipFilePath
  377. * @return
  378. * @throws Exception
  379. */
  380. public static List<String> uncompress(String zipFilePath) throws Exception {
  381. File file = new File(zipFilePath);
  382. return uncompress(zipFilePath, file.getParent());
  383. }
  384. // public static void main(String[] args) {
  385. // try {
  386. // // 压缩单个
  387. // ZipUtils.compress("D:\\TEST\\abc一二三123.txt");
  388. // // 压缩多个
  389. // List<File> files = new ArrayList<File>();
  390. // files.add(new File("D:\\TEST\\WebappReport.jrxml"));
  391. // files.add(new File("D:\\TEST\\WebappReport.jasper"));
  392. // File destFile = new File("D:\\TEST\\WebappReport2.zip");
  393. // ZipUtils.compress(files.toArray(new File[files.size()]), destFile);
  394. // // 解压到指定目录
  395. // ZipUtils.uncompress("D:\\TEST\\WebappReport2.zip", "D:\\TEST\\a");
  396. // // 解压到当前目录
  397. // ZipUtils.uncompress("D:\\TEST\\abc一二三123.zip");
  398. // }
  399. // catch (Exception e) {
  400. // // TODO Auto-generated catch block
  401. // e.printStackTrace();
  402. // }
  403. // }
  404. }