原文:http://snowolf.iteye.com/blog/642492

JavaEye的朋友跟我说:“你一口气把ZIP压缩和解压缩都写到一个帖子里,我看起来很累,不如分开好阅读”。ok,面向读者需求,我做调整,这里单说ZIP解压缩!

解压缩与压缩运作方式相反,原理大抵相同,由ZipInputStream通过read方法对数据解压,同时需要通过CheckedInputStream设置冗余校验码,如:

  1. CheckedInputStream cis = new CheckedInputStream(new FileInputStream(
  2. srcFile), new CRC32());
  3. ZipInputStream zis = new ZipInputStream(cis);

需要注意的是,在构建解压文件时,需要考虑目录的自动创建,这里通过递归方式逐层创建父目录,如下所示:

  1. /**
  2. * 文件探针
  3. *
  4. *
  5. * 当父目录不存在时,创建目录!
  6. *
  7. *
  8. * @param dirFile
  9. */
  10. private static void fileProber(File dirFile) {
  11. File parentFile = dirFile.getParentFile();
  12. if (!parentFile.exists()) {
  13. // 递归寻找上级目录
  14. fileProber(parentFile);
  15. parentFile.mkdir();
  16. }
  17. }

在压缩的时候,我们是将一个一个文件作为压缩添加项(ZipEntry)添加至压缩包中,解压缩就要将一个一个压缩项从压缩包中提取出来,如下所示:

  1. /**
  2. * 文件 解压缩
  3. *
  4. * @param destFile
  5. *            目标文件
  6. * @param zis
  7. *            ZipInputStream
  8. * @throws Exception
  9. */
  10. private static void decompress(File destFile, ZipInputStream zis)
  11. throws Exception {
  12. ZipEntry entry = null;
  13. while ((entry = zis.getNextEntry()) != null) {
  14. // 文件
  15. String dir = destFile.getPath() + File.separator + entry.getName();
  16. File dirFile = new File(dir);
  17. // 文件检查
  18. fileProber(dirFile);
  19. if (entry.isDirectory()){
  20. dirFile.mkdirs();
  21. } else {
  22. decompressFile(dirFile, zis);
  23. }
  24. zis.closeEntry();
  25. }
  26. }

最核心的解压缩实现,其实与压缩实现非常相似,代码如下所示:

  1. /**
  2. * 文件解压缩
  3. *
  4. * @param destFile
  5. *            目标文件
  6. * @param zis
  7. *            ZipInputStream
  8. * @throws Exception
  9. */
  10. private static void decompressFile(File destFile, ZipInputStream zis)
  11. throws Exception {
  12. BufferedOutputStream bos = new BufferedOutputStream(
  13. new FileOutputStream(destFile));
  14. int count;
  15. byte data[] = new byte[BUFFER];
  16. while ((count = zis.read(data, 0, BUFFER)) != -1) {
  17. bos.write(data, 0, count);
  18. }
  19. bos.close();
  20. }

来个完整的解压缩实现,代码如下:

  1. /**
  2. * 2010-4-12
  3. */
  4. package org.zlex.commons.io;
  5. import java.io.BufferedInputStream;
  6. import java.io.BufferedOutputStream;
  7. import java.io.File;
  8. import java.io.FileInputStream;
  9. import java.io.FileOutputStream;
  10. import java.util.zip.CRC32;
  11. import java.util.zip.CheckedInputStream;
  12. import java.util.zip.CheckedOutputStream;
  13. import java.util.zip.ZipEntry;
  14. import java.util.zip.ZipInputStream;
  15. import java.util.zip.ZipOutputStream;
  16. /**
  17. * ZIP压缩工具
  18. *
  19. * @author 梁栋
  20. * @since 1.0
  21. */
  22. public class ZipUtils {
  23. public static final String EXT = ".zip";
  24. private static final String BASE_DIR = "";
  25. private static final String PATH = File.separator;
  26. private static final int BUFFER = 1024;
  27. /**
  28. * 文件 解压缩
  29. *
  30. * @param srcPath
  31. *            源文件路径
  32. *
  33. * @throws Exception
  34. */
  35. public static void decompress(String srcPath) throws Exception {
  36. File srcFile = new File(srcPath);
  37. decompress(srcFile);
  38. }
  39. /**
  40. * 解压缩
  41. *
  42. * @param srcFile
  43. * @throws Exception
  44. */
  45. public static void decompress(File srcFile) throws Exception {
  46. String basePath = srcFile.getParent();
  47. decompress(srcFile, basePath);
  48. }
  49. /**
  50. * 解压缩
  51. *
  52. * @param srcFile
  53. * @param destFile
  54. * @throws Exception
  55. */
  56. public static void decompress(File srcFile, File destFile) throws Exception {
  57. CheckedInputStream cis = new CheckedInputStream(new FileInputStream(
  58. srcFile), new CRC32());
  59. ZipInputStream zis = new ZipInputStream(cis);
  60. decompress(destFile, zis);
  61. zis.close();
  62. }
  63. /**
  64. * 解压缩
  65. *
  66. * @param srcFile
  67. * @param destPath
  68. * @throws Exception
  69. */
  70. public static void decompress(File srcFile, String destPath)
  71. throws Exception {
  72. decompress(srcFile, new File(destPath));
  73. }
  74. /**
  75. * 文件 解压缩
  76. *
  77. * @param srcPath
  78. *            源文件路径
  79. * @param destPath
  80. *            目标文件路径
  81. * @throws Exception
  82. */
  83. public static void decompress(String srcPath, String destPath)
  84. throws Exception {
  85. File srcFile = new File(srcPath);
  86. decompress(srcFile, destPath);
  87. }
  88. /**
  89. * 文件 解压缩
  90. *
  91. * @param destFile
  92. *            目标文件
  93. * @param zis
  94. *            ZipInputStream
  95. * @throws Exception
  96. */
  97. private static void decompress(File destFile, ZipInputStream zis)
  98. throws Exception {
  99. ZipEntry entry = null;
  100. while ((entry = zis.getNextEntry()) != null) {
  101. // 文件
  102. String dir = destFile.getPath() + File.separator + entry.getName();
  103. File dirFile = new File(dir);
  104. // 文件检查
  105. fileProber(dirFile);
  106. if (entry.isDirectory()) {
  107. dirFile.mkdirs();
  108. } else {
  109. decompressFile(dirFile, zis);
  110. }
  111. zis.closeEntry();
  112. }
  113. }
  114. /**
  115. * 文件探针
  116. *
  117. *
  118. * 当父目录不存在时,创建目录!
  119. *
  120. *
  121. * @param dirFile
  122. */
  123. private static void fileProber(File dirFile) {
  124. File parentFile = dirFile.getParentFile();
  125. if (!parentFile.exists()) {
  126. // 递归寻找上级目录
  127. fileProber(parentFile);
  128. parentFile.mkdir();
  129. }
  130. }
  131. /**
  132. * 文件解压缩
  133. *
  134. * @param destFile
  135. *            目标文件
  136. * @param zis
  137. *            ZipInputStream
  138. * @throws Exception
  139. */
  140. private static void decompressFile(File destFile, ZipInputStream zis)
  141. throws Exception {
  142. BufferedOutputStream bos = new BufferedOutputStream(
  143. new FileOutputStream(destFile));
  144. int count;
  145. byte data[] = new byte[BUFFER];
  146. while ((count = zis.read(data, 0, BUFFER)) != -1) {
  147. bos.write(data, 0, count);
  148. }
  149. bos.close();
  150. }
  151. }

其实,理解了ZIP的工作原理,这些代码看起来很好懂!

把刚才做的压缩文件再用上述代码解开看看,测试用例如下:

  1. /**
  2. * 2010-4-12
  3. */
  4. package org.zlex.commons.io;
  5. import static org.junit.Assert.*;
  6. import org.junit.Test;
  7. /**
  8. *
  9. * @author 梁栋
  10. * @version 1.0
  11. * @since 1.0
  12. */
  13. public class ZipUtilsTest {
  14. /**
  15. *
  16. */
  17. @Test
  18. public void test() throws Exception {
  19. // 解压到指定目录
  20. ZipUtils.decompress("d:\\f.txt.zip", "d:\\ff");
  21. // 解压到当前目录
  22. ZipUtils.decompress("d:\\fd.zip");
  23. }
  24. }

完整代码详见附件!

java原生的ZIP实现虽然在压缩时会因与系统字符集不符产生中文乱码,但在解压缩后,字符集即可恢复。

除了java原生的ZIP实现外,commons和ant也提供了相应的ZIP算法实现,有机会我再一一介绍!

Java压缩技术(三) ZIP解压缩——Java原生实现的更多相关文章

  1. Java压缩技术(二) ZIP压缩——Java原生实现

    原文:http://snowolf.iteye.com/blog/642298 去年整理了一篇ZLib算法Java实现(Java压缩技术(一) ZLib),一直惦记却没时间补充.今天得空,整理一下ZI ...

  2. Java压缩/解压.zip、.tar.gz、.tar.bz2(支持中文)

    本文介绍Java压缩/解压.zip..tar.gz..tar.bz2的方式. 对于zip文件:使用java.util.zip.ZipEntry 和 java.util.zip.ZipFile,通过设置 ...

  3. Java基础:三步学会Java Socket编程

    Java基础:三步学会Java Socket编程 http://tech.163.com 2006-04-10 09:17:18 来源: java-cn 网友评论11 条 论坛        第一步 ...

  4. Java压缩技术的学习

    由于工作的需要,经常要手动去打上线安装包,为了方便,自己写程序去帮助打包.使用过Unix或者Linux的人都基本上都用过tar打包以及gzip压缩,但在Windows下使用得最多的压缩还是RAR和Zi ...

  5. java 压缩技术

    package zip; import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStr ...

  6. JAVA压缩解压ZIP文件,中文乱码还需要ANT.JAR包

    package zip; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStrea ...

  7. java 压缩和解压zip包

    网上有关压缩和解压zip包的博文一大堆,我随便找了一个.看了看,依照自己的须要改动了一下,与各位分享一下,希望各位大神指正: package com.wangpeng.utill; import ja ...

  8. Java虚拟机(三):Java 类的加载机制

    1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构 ...

  9. 赶紧收藏!王者级别的Java多线程技术笔记,我java小菜鸡愿奉你为地表最强!

    Java多线程技术概述 介绍多线程之前要介绍线程,介绍线程则离不开进程. 首先 , 进程 :是一个正在执行中的程序,每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元: 线程:就 ...

随机推荐

  1. Java_Web三大框架之Hibernate 入门(一)

    一.Hibernate简介: Hibernate作者——Gavin King Hibernate创始人 < Hibernate in action >作者 EJB 3.0的Entity b ...

  2. js post一个对象 在C#中怎么接收? 未解决

    这个在C#中怎么接收?

  3. 20190625_mysql5.7查看及其解锁_被锁的表

    [root@localhost ~]# mysql -u myroot -pEnter password: mysql> show OPEN TABLES where In_use > 0 ...

  4. Centos7下mysql的主从配置

    最近,有朋友业务并发量比较大,让我帮他配置个主从,来缓解数据库的压力.下面就是我配置的,有需要的朋友可以借鉴下. 首先,我得到2台服务器: 172.18.2.142(主) 172.18.2.141(从 ...

  5. css 字体单位之间的区分以及字体响应式实现

    问题场景: 在实现响应式布局的过程中,如何设置字体大小在不同的视窗尺寸以及不同的移动设备的可读性? 需要了解的有: 1.px,em,pt之间的换算关系 1em = 16px 1px  = 1/16 e ...

  6. BZOJ 1631 Usaco 2007 Feb. Cow Party

    [题解] 最短路裸题.. 本题要求出每个点到终点走最短路来回的距离,因此我们先跑一遍最短路得出每个点到终点的最短距离,然后把边反向再跑一遍最短路,两次结果之和即是答案. #include<cst ...

  7. codeforeces近日题目小结

    题目源自codeforeces的三场contest contest/1043+1055+1076 目前都是solved 6/7,都差了最后一题 简单题: contest/1043/E: 先不考虑m个限 ...

  8. 【MariaDB】MariaDB vs MySQL - 特性

    原文链接: https://mariadb.com/kb/en/mariadb-vs-mysql-features/ xiaomo译------ 支持更多的存储引擎 除了标配的MyISAM, BLAC ...

  9. 清北学堂模拟赛d2t1 一道图论神题(god)

    题目描述 LYK有一张无向图G={V,E},这张无向图有n个点m条边组成.并且这是一张带权图,只有点权. LYK想把这个图删干净,它的方法是这样的.每次选择一个点,将它删掉,但删这个点是需要代价的.假 ...

  10. H - Seek the Name, Seek the Fame

    The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the l ...