Java压缩技术(一) ZLib),一直惦记却没时间补充。今天得空,整理一下ZIP的java原生实现。

看了几篇zip压缩算法的帖子,讲的算是比较细致了,但就是没有对应的解压缩实现,太惜败了!

我就喜欢没事做总结,稍作整理,将其收纳!

相关链接:

Java压缩技术(一) ZLib

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

Java压缩技术(三) ZIP解压缩——Java原生实现

Java压缩技术(四) GZIP——Java原生实现

Java压缩技术(五) GZIP相关——浏览器解析

Java压缩技术(六) BZIP2——Commons实现

Java压缩技术(七) TAR——Commons实现

查过相关资料后才知道,ZIP应该算作归档类的压缩算法,每一门学科都可深可浅!

闲言少叙,先说ZIP压缩。

zip压缩需要通过ZipOutputStream 执行write方法将压缩数据写到指定输出流中。

注意,这里应先使用CheckedOutputStream 指定文件校验算法。(通常使用CRC32算法)。代码如下所示:

CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(destPath), new CRC32());

ZipOutputStream zos = new ZipOutputStream(cos);

接下来,需要将待压缩文件以ZipEntry的方式追加到压缩文件中,如下所示:

/**

* 压缩包内文件名定义

*

*

* 如果有多级目录,那么这里就需要给出包含目录的文件名

* 如果用WinRAR打开压缩包,中文名将显示为乱码

*

*/

ZipEntry entry = new ZipEntry(dir + file.getName());

zos.putNextEntry(entry);

ZipEntry就是压缩包中的每一个实体!

完成上述准备后,就可以执行压缩操作了。实际上,就是执行ZipOutputStream类的write方法,如下所示:

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(

file));

int count;

byte data[] = new byte[BUFFER];

while ((count = bis.read(data, 0, BUFFER)) != -1) {

zos.write(data, 0, count);

}

bis.close();

当然,如果待添加的压缩项是一个目录。那么,需要通过递归的方式指定最终的压缩项。

如果要添加一个空目录,注意使用符号"/"(String PATH="/";)作为添加项名字结尾符!

递归构建目录压缩,代码如下:

/**

* 压缩

*

* @param srcFile

* 源路径

* @param zos

* ZipOutputStream

* @param basePath

* 压缩包内相对路径

* @throws Exception

*/

private static void compress(File srcFile, ZipOutputStream zos,

String basePath) throws Exception {

if (srcFile.isDirectory()) {

compressDir(srcFile, zos, basePath);

} else {

compressFile(srcFile, zos, basePath);

}

}

/**

* 压缩目录

*

* @param dir

* @param zos

* @param basePath

* @throws Exception

*/

private static void compressDir(File dir, ZipOutputStream zos,

String basePath) throws Exception {

File[] files = dir.listFiles();

// 构建空目录

if (files.length < 1) {

ZipEntry entry = new ZipEntry(basePath + dir.getName() + PATH);

zos.putNextEntry(entry);

zos.closeEntry();

}

for (File file : files) {

// 递归压缩

compress(file, zos, basePath + dir.getName() + PATH);

}

}

x是一个空目录,用WinRAR打开后,可以看到这个目录下还有一个空文件名文件!

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

/**

* 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 = "/";

private static final int BUFFER = 1024;

/**

* 压缩

*

* @param srcFile

* @throws Exception

*/

public static void compress(File srcFile) throws Exception {

String name = srcFile.getName();

String basePath = srcFile.getParent();

String destPath = basePath + name + EXT;

compress(srcFile, destPath);

}

/**

* 压缩

*

* @param srcFile

* 源路径

* @param destPath

* 目标路径

* @throws Exception

*/

public static void compress(File srcFile, File destFile) throws Exception {

// 对输出文件做CRC32校验

CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(

destFile), new CRC32());

ZipOutputStream zos = new ZipOutputStream(cos);

compress(srcFile, zos, BASE_DIR);

zos.flush();

zos.close();

}

/**

* 压缩文件

*

* @param srcFile

* @param destPath

* @throws Exception

*/

public static void compress(File srcFile, String destPath) throws Exception {

compress(srcFile, new File(destPath));

}

/**

* 压缩

*

* @param srcFile

* 源路径

* @param zos

* ZipOutputStream

* @param basePath

* 压缩包内相对路径

* @throws Exception

*/

private static void compress(File srcFile, ZipOutputStream zos,

String basePath) throws Exception {

if (srcFile.isDirectory()) {

compressDir(srcFile, zos, basePath);

} else {

compressFile(srcFile, zos, basePath);

}

}

/**

* 压缩

*

* @param srcPath

* @throws Exception

*/

public static void compress(String srcPath) throws Exception {

File srcFile = new File(srcPath);

compress(srcFile);

}

/**

* 文件压缩

*

* @param srcPath

* 源文件路径

* @param destPath

* 目标文件路径

*

*/

public static void compress(String srcPath, String destPath)

throws Exception {

File srcFile = new File(srcPath);

compress(srcFile, destPath);

}

/**

* 压缩目录

*

* @param dir

* @param zos

* @param basePath

* @throws Exception

*/

private static void compressDir(File dir, ZipOutputStream zos,

String basePath) throws Exception {

File[] files = dir.listFiles();

// 构建空目录

if (files.length < 1) {

ZipEntry entry = new ZipEntry(basePath + dir.getName() + PATH);

zos.putNextEntry(entry);

zos.closeEntry();

}

for (File file : files) {

// 递归压缩

compress(file, zos, basePath + dir.getName() + PATH);

}

}

/**

* 文件压缩

*

* @param file

* 待压缩文件

* @param zos

* ZipOutputStream

* @param dir

* 压缩文件中的当前路径

* @throws Exception

*/

private static void compressFile(File file, ZipOutputStream zos, String dir)

throws Exception {

/**

* 压缩包内文件名定义

*

*

* 如果有多级目录,那么这里就需要给出包含目录的文件名

* 如果用WinRAR打开压缩包,中文名将显示为乱码

*

*/

ZipEntry entry = new ZipEntry(dir + file.getName());

zos.putNextEntry(entry);

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(

file));

int count;

byte data[] = new byte[BUFFER];

while ((count = bis.read(data, 0, BUFFER)) != -1) {

zos.write(data, 0, count);

}

bis.close();

zos.closeEntry();

}

}

来做个简单的测试:

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.compress("d:\\f.txt");

// 压缩目录

ZipUtils.compress("d:\\fd");

}

}

现在用WinRAR打开看看,是不是效果几乎一致?

当然,上述代码有所不足之处主要是中文名称乱码问题。用java原生ZIP实现压缩后得到的压缩包,与系统的字符集不同,文件/目录名将出现乱码。这是所有归档压缩都会遇到的问题。对于这种问题,Commons Copress提供了解决方案!

对于解压缩,请关注后续内容!

相关链接:

Java压缩技术(一) ZLib

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

Java压缩技术(三) ZIP解压缩——Java原生实现

Java压缩技术(四) GZIP——Java原生实现

Java压缩技术(五) GZIP相关——浏览器解析

Java压缩技术(六) BZIP2——Commons实现

Java压缩技术(七) TAR——Commons实现

16

8

分享到:

2010-04-13 00:02

浏览 59599

评论

6 楼

夏季浅忆-卖小子

2017-11-27

按照你这个方法压缩出来的文件使用winRAR解压时候提示文件被损坏无法解压

5 楼

wjc19871222

2017-11-17

niubist

太牛逼了,学习了

3 楼

wzwdcld

2015-09-11

楼主这个也出书了?

1 楼

lijie1819

2012-05-25

能否将两个文件压缩在一起呢

java zip_Java压缩技术(二) ZIP压缩——Java原生实现相关推荐

  1. Python将Pandas中Dataframe数据保存为gzip/zip文件:gzip压缩文件、zip压缩文件

    Python将Pandas中Dataframe数据保存为gzip/zip文件:gzip压缩文件.zip压缩文件 目录 Python将Pandas中Dataframe数据保存为gzip/zip文件:gz ...

  2. java 压缩 空目录_java zip压缩与解压-支持空目录,保留文件修改时间

    java zip压缩与解压-支持空目录,保留文件修改时间. 依赖于commons-io,commons-compress [Java]代码 import java.io.BufferedInputSt ...

  3. Java字节码技术(二)字节码增强之ASM、JavaAssist、Agent、Instrumentation

    文章目录 前言 从AOP说起 静态代理 动态代理 JavaProxy CGLIB 字节码增强实现AOP ASM JavaAssist 运行时类加载 Instrumentation接口 JavaAgen ...

  4. java有趣的技术分享ppt,java面试数据结构与算法高频考

    前言 本文涵盖了阿里巴巴.腾讯.字节跳动.京东.华为等大厂的Java面试真题,不管你是要面试大厂还是普通的互联网公司,这些面试题对你肯定是有帮助的,毕竟大厂一定是行业的发展方向标杆,很多公司的面试官同 ...

  5. linux系统zip压缩命令,linux zip 压缩命令

    linux   zip命令 的基本用法是: zip  [参数] [打包后的文件名] [打包的目录路径] linux   zip命令 参数列表: -a     将文件转成ASCII模式 -F     尝 ...

  6. linux 压缩根目录文件,Linux操作系统下如何压缩文件? zip压缩命令使用

    Linux zip命令用于压缩文件. zip是个使用广泛的压缩程序,文件经它压缩后会另外产生具有".zip"扩展名的压缩文件. 在linux操作系统中,使用zip命令进行文件压缩时 ...

  7. java 集成 protobuf及二次压缩

    一.创建springboot项目 1.创建proto文件目录 和 proto文件生成的java对象包 ​ 2.pom 中添加依赖包 ## 版本 <grpc-version>1.6.1< ...

  8. Java学习笔记(二一)——Java 泛型

    [前面的话] 最近脸好干,掉皮,需要买点化妆品了. Java泛型好好学习一下. [定义] 一.泛型的定义主要有以下两种: 在程序编码中一些包含类型参数的类型,也就是说泛型的参数只可以代表类,不能代表个 ...

  9. php zip压缩命令,php zip压缩文件

    /** * 压缩文件 * @param string $path 需要压缩的文件[夹]路径 * @param string $savedir 压缩文件所保存的目录 * @return array zi ...

  10. java推送技术_java网络编程 - java服务器推送技术系列方案实战

    前言 服务器推送技术(又名Comet)是建立在ARP基础之上的一种非常实用的技术,它广泛应用于Web端,手机APP应用端等.具体很多场景都需要此技术的支撑,包括扫码登录.扫码支付.网页支付.端到端消息 ...

最新文章

  1. TCP/IP四层模型和OSI七层模型
  2. MapReduce框架Mapper和Reducer类源码分析
  3. Redis学习-String
  4. RabbitMQ之消息持久化
  5. 【错误记录】GitHub 提交代码失败、获取代码失败、连接超时、权限错误、ping 请求连接超时 ( 查找域名对应 IP | 设置 host 文件 )
  6. Kingbase金仓更改表空间
  7. sql-server基础三(select 、update、insert,delete)
  8. 定时器表达式各组成部分详解
  9. 蔬菜大棚成本_蔬菜大棚建设标准和成本
  10. Spring DI(依赖注入)构造器注入篇
  11. C++_程序内存模型_内存四区_代码区_全局区_每种区域都存放什么样的变量---C++语言工作笔记028
  12. 【Computer Organization笔记12】流水线技术概述
  13. matlab struct 结构体
  14. 软件加入使用时间_2020年,加入“midi音乐制作讲堂”内部会员,学音乐制作变得更简单...
  15. linux服务器上的cad病毒,Linux挖矿病毒的清除与分析
  16. vue 微信公众号 前端开发
  17. Android信息处理机制
  18. 【2022刷题】受伤的皇后
  19. 基于预测分析表法的语法分析程序
  20. 怎么查看自己微信支付宝绑定银行卡号

热门文章

  1. 20191206每日一句
  2. AR/MR技术的应用
  3. Atitit 获取SqlSessionFactory的三种方式 目录 第一节 DataSource 方式 1 第二节 读取sprbt Url方式 ByteArrayInputStream 1 第三节
  4. Atitit 2016 技术趋势与没落技术 目录 1.1. 流水线 即代码通过编码而非配置CI/CD运行工具的方式,来定义部署 流水线 1 1.2. 将APIs当作产品 1 1.3. 无服务器架构
  5. Atitit 面向对象弊端与问题 坏处 缺点
  6. Atitit.软件与编程语言中的锁机制原理attilax总结
  7. paip. java resin 远程 调试 java resin remote debug
  8. paip.pyqt python qt 最新版本环境最佳实践
  9. 主数据——共享数据的核心,数据资产的灵魂
  10. 阿里云存储:做深基础,助力新基建 | 凌云时刻