Java压缩技术(三) ZIP解压缩——Java原生实现
2024-08-31 01:30:06
原文: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);
需要注意的是,在构建解压文件时,需要考虑目录的自动创建,这里通过递归方式逐层创建父目录,如下所示:
- /**
- * 文件探针
- *
- *
- * 当父目录不存在时,创建目录!
- *
- *
- * @param dirFile
- */
- private static void fileProber(File dirFile) {
- File parentFile = dirFile.getParentFile();
- if (!parentFile.exists()) {
- // 递归寻找上级目录
- fileProber(parentFile);
- parentFile.mkdir();
- }
- }
在压缩的时候,我们是将一个一个文件作为压缩添加项(ZipEntry)添加至压缩包中,解压缩就要将一个一个压缩项从压缩包中提取出来,如下所示:
- /**
- * 文件 解压缩
- *
- * @param destFile
- * 目标文件
- * @param zis
- * ZipInputStream
- * @throws Exception
- */
- 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();
- }
- }
最核心的解压缩实现,其实与压缩实现非常相似,代码如下所示:
- /**
- * 文件解压缩
- *
- * @param destFile
- * 目标文件
- * @param zis
- * ZipInputStream
- * @throws Exception
- */
- 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();
- }
来个完整的解压缩实现,代码如下:
- /**
- * 2010-4-12
- */
- 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;
- /**
- * ZIP压缩工具
- *
- * @author 梁栋
- * @since 1.0
- */
- 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;
- /**
- * 文件 解压缩
- *
- * @param srcPath
- * 源文件路径
- *
- * @throws Exception
- */
- public static void decompress(String srcPath) throws Exception {
- File srcFile = new File(srcPath);
- decompress(srcFile);
- }
- /**
- * 解压缩
- *
- * @param srcFile
- * @throws Exception
- */
- public static void decompress(File srcFile) throws Exception {
- String basePath = srcFile.getParent();
- decompress(srcFile, basePath);
- }
- /**
- * 解压缩
- *
- * @param srcFile
- * @param destFile
- * @throws Exception
- */
- 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();
- }
- /**
- * 解压缩
- *
- * @param srcFile
- * @param destPath
- * @throws Exception
- */
- public static void decompress(File srcFile, String destPath)
- throws Exception {
- decompress(srcFile, new File(destPath));
- }
- /**
- * 文件 解压缩
- *
- * @param srcPath
- * 源文件路径
- * @param destPath
- * 目标文件路径
- * @throws Exception
- */
- public static void decompress(String srcPath, String destPath)
- throws Exception {
- File srcFile = new File(srcPath);
- decompress(srcFile, destPath);
- }
- /**
- * 文件 解压缩
- *
- * @param destFile
- * 目标文件
- * @param zis
- * ZipInputStream
- * @throws Exception
- */
- 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();
- }
- }
- /**
- * 文件探针
- *
- *
- * 当父目录不存在时,创建目录!
- *
- *
- * @param dirFile
- */
- private static void fileProber(File dirFile) {
- File parentFile = dirFile.getParentFile();
- if (!parentFile.exists()) {
- // 递归寻找上级目录
- fileProber(parentFile);
- parentFile.mkdir();
- }
- }
- /**
- * 文件解压缩
- *
- * @param destFile
- * 目标文件
- * @param zis
- * ZipInputStream
- * @throws Exception
- */
- 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的工作原理,这些代码看起来很好懂!
把刚才做的压缩文件再用上述代码解开看看,测试用例如下:
- /**
- * 2010-4-12
- */
- package org.zlex.commons.io;
- import static org.junit.Assert.*;
- import org.junit.Test;
- /**
- *
- * @author 梁栋
- * @version 1.0
- * @since 1.0
- */
- 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算法实现,有机会我再一一介绍!
最新文章
- Visual Studio 版本转换工具WPF版开源了
- Android编译过程中的碎碎念
- Thread.join()方法
- delphi 获取颜色值的RGB
- python获取当前日期前后N天或N月的日期
- UE4.7的IOS发布和调试的相关问题
- linux安装iscsi target,make时出错,解决方法
- C#多线程及GDI(Day 23)
- HDU 2063 最大匹配的基础题
- jsp 的四个作用域 :page、request、session和application的区别 (转)
- ImCash:第一个集多功能于一身的数字资产平台
- django自制后台左侧导航代码
- [Codeforces Round #516][Codeforces 1063B/1064D. Labyrinth]
- Zynq系列FPGA如何固化bit文件到QSPI_Flash
- 用crontab部署定时任务
- HDU5985 Lucky Coins 概率dp
- Javascript中的this指向。
- 洛谷 P2678 跳石头
- OCM_第五天课程:Section2 —》AGENT 的安装 、GC 的使用
- F - Rails
热门文章
- 微信小程序php后台实现
- 结果缓冲区 resbuf具体用法
- jquery操作元素之间相邻的元素的获取方式
- What is the difference between rhel 6 and rhel7
- Async/await语法糖实现(Generator)
- How To: set udev rule for setting the disk permission on ASM disks when using multipath on Linux 6.x
- c/c++排坑(4) -- c/c++中返回局部变量
- python中enumerate( )函数的使用
- 【JAVA】AES加密
- 746. Min Cost Climbing Stairs(动态规划)