标签:
原文:http://snowolf.iteye.com/blog/642492
JavaEye的朋友跟我说:“你一口气把ZIP压缩和解压缩都写到一个帖子里,我看起来很累,不如分开好阅读”。ok,面向读者需求,我做调整,这里单说ZIP解压缩!
解压缩与压缩运作方式相反,原理大抵相同,由ZipInputStream通过read方法对数据解压,同时需要通过CheckedInputStream设置冗余校验码,如:
- CheckedInputStream cis = new CheckedInputStream(new FileInputStream(
- srcFile), new CRC32());
-
- ZipInputStream zis = new ZipInputStream(cis);
需要注意的是,在构建解压文件时,需要考虑目录的自动创建,这里通过递归方式逐层创建父目录,如下所示:
- private static void fileProber(File dirFile) {
-
- File parentFile = dirFile.getParentFile();
- if (!parentFile.exists()) {
-
-
- fileProber(parentFile);
-
- parentFile.mkdir();
- }
-
- }
在压缩的时候,我们是将一个一个文件作为压缩添加项(ZipEntry)添加至压缩包中,解压缩就要将一个一个压缩项从压缩包中提取出来,如下所示:
- private static void decompress(File destFile, ZipInputStream zis)
- throws Exception {
-
- ZipEntry entry = null;
- while ((entry = zis.getNextEntry()) != null) {
-
-
- String dir = destFile.getPath() + File.separator + entry.getName();
-
- File dirFile = new File(dir);
-
-
- fileProber(dirFile);
-
- if (entry.isDirectory()){
- dirFile.mkdirs();
- } else {
- decompressFile(dirFile, zis);
- }
-
- zis.closeEntry();
- }
- }
最核心的解压缩实现,其实与压缩实现非常相似,代码如下所示:
- private static void decompressFile(File destFile, ZipInputStream zis)
- throws Exception {
-
- BufferedOutputStream bos = new BufferedOutputStream(
- new FileOutputStream(destFile));
-
- int count;
- byte data[] = new byte[BUFFER];
- while ((count = zis.read(data, 0, BUFFER)) != -1) {
- bos.write(data, 0, count);
- }
-
- bos.close();
- }
来个完整的解压缩实现,代码如下:
- package org.zlex.commons.io;
-
- import java.io.BufferedInputStream;
- import java.io.BufferedOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.util.zip.CRC32;
- import java.util.zip.CheckedInputStream;
- import java.util.zip.CheckedOutputStream;
- import java.util.zip.ZipEntry;
- import java.util.zip.ZipInputStream;
- import java.util.zip.ZipOutputStream;
-
- public class ZipUtils {
-
- public static final String EXT = ".zip";
- private static final String BASE_DIR = "";
- private static final String PATH = File.separator;
- private static final int BUFFER = 1024;
-
-
- public static void decompress(String srcPath) throws Exception {
- File srcFile = new File(srcPath);
-
- decompress(srcFile);
- }
-
-
- public static void decompress(File srcFile) throws Exception {
- String basePath = srcFile.getParent();
- decompress(srcFile, basePath);
- }
-
-
- public static void decompress(File srcFile, File destFile) throws Exception {
-
- CheckedInputStream cis = new CheckedInputStream(new FileInputStream(
- srcFile), new CRC32());
-
- ZipInputStream zis = new ZipInputStream(cis);
-
- decompress(destFile, zis);
-
- zis.close();
-
- }
-
-
- public static void decompress(File srcFile, String destPath)
- throws Exception {
- decompress(srcFile, new File(destPath));
-
- }
-
-
- public static void decompress(String srcPath, String destPath)
- throws Exception {
-
- File srcFile = new File(srcPath);
- decompress(srcFile, destPath);
- }
-
-
- private static void decompress(File destFile, ZipInputStream zis)
- throws Exception {
-
- ZipEntry entry = null;
- while ((entry = zis.getNextEntry()) != null) {
-
-
- String dir = destFile.getPath() + File.separator + entry.getName();
-
- File dirFile = new File(dir);
-
-
- fileProber(dirFile);
-
- if (entry.isDirectory()) {
- dirFile.mkdirs();
- } else {
- decompressFile(dirFile, zis);
- }
-
- zis.closeEntry();
- }
- }
-
-
- private static void fileProber(File dirFile) {
-
- File parentFile = dirFile.getParentFile();
- if (!parentFile.exists()) {
-
-
- fileProber(parentFile);
-
- parentFile.mkdir();
- }
-
- }
-
-
- private static void decompressFile(File destFile, ZipInputStream zis)
- throws Exception {
-
- BufferedOutputStream bos = new BufferedOutputStream(
- new FileOutputStream(destFile));
-
- int count;
- byte data[] = new byte[BUFFER];
- while ((count = zis.read(data, 0, BUFFER)) != -1) {
- bos.write(data, 0, count);
- }
-
- bos.close();
- }
-
- }
其实,理解了ZIP的工作原理,这些代码看起来很好懂!
把刚才做的压缩文件再用上述代码解开看看,测试用例如下:
- package org.zlex.commons.io;
-
- import static org.junit.Assert.*;
-
- import org.junit.Test;
-
- public class ZipUtilsTest {
-
-
- @Test
- public void test() throws Exception {
-
- ZipUtils.decompress("d:\\f.txt.zip", "d:\\ff");
-
- ZipUtils.decompress("d:\\fd.zip");
- }
-
- }
完整代码详见附件!
java原生的ZIP实现虽然在压缩时会因与系统字符集不符产生中文乱码,但在解压缩后,字符集即可恢复。
除了java原生的ZIP实现外,commons和ant也提供了相应的ZIP算法实现,有机会我再一一介绍!![技术分享](http://snowolf.iteye.com/images/smiles/icon_biggrin.gif)
Java压缩技术(三) ZIP解压缩——Java原生实现
标签:
原文地址:http://www.cnblogs.com/jqmtony/p/5575111.html