java多层级zip解压

前言

  项目中偶然需要,希望能处理嵌套的压缩包,但是又不希望把文件解压处理。原本不希望重复造轮子,但没有发现很好用的现成案例,就简单处理了一下。

正文

  java做zip解压一般使用 ZipFile​ 或者 ZipInputStream​。

  在实际使用中,遇到了zip清单属性无法读取的报错,最终采用了apache的ZipArchiveInputStream。主要是allowStoredEntriesWithDataDescriptor​属性。

  代码完整使用的依赖如下:

	    <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.26</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
</dependency>

  代码主要为符合业务需求而写,比较简陋。支持单次解压和递归解压,均通过回调返回缓冲流(无法关闭的缓冲流)。

  必须要注意的是,一定不能提前关闭ZipArchiveInputStream,这个流一次会在getNextZipEntry后再次填充。

  回调如果采用字节对内存的压力可能会比较大,所以通过缓冲流返回数据。为防止多人协作中出现误关闭流,使用不关闭源流的缓冲流工具。

  如果有需要解压指定包,在入参加一个filter就可以实现。

完整代码实例

package xxx;

import java.io.BufferedInputStream;

import java.io.IOException;

import java.io.InputStream; /**
  • 用于辅助的不关闭原流的缓冲流

    */

    public class NoCloseBufferStream extends BufferedInputStream { public NoCloseBufferStream(InputStream in) {

    super(in);

    } @Override

    public void close() throws IOException {

    //不实现任何东西就不会关闭原流

    }
}
package xxx; //your package

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files; /**
* 注意:初始的输入流是不会主动关闭的
*
* @author 铁流
*/
@Slf4j
public class UnZipUtil { public static void main(String[] args) throws IOException { try (InputStream inputStream = Files.newInputStream(new File("/Users/tieliu/Desktop/test/aaaa.zip").toPath());) {
loopUnzip(inputStream, (level, path, basePath, is) -> {
is.close();
log.info(" level: {},path: {},basePath: {}", level, path, basePath);
return true;
});
}
} /**
* 递归解压zip,只能解压zip后缀名的压缩文件
*
* @param inputStream 初始文件输入流
* @param loopCallBack 递归回调,返回值控制是否向下递归
* @throws IOException 文件流异常
*/
public static void loopUnzip(InputStream inputStream, LoopCallBack loopCallBack) throws IOException {
loopUnzip(inputStream, 0, "", loopCallBack);
} private static void loopUnzip(InputStream inputStream, int level, String basePath, LoopCallBack loopCallBack) throws IOException {
decompress(inputStream, (path, is) -> {
// 此处决定是否继续向下
if (loopCallBack.call(level, path, basePath, is) && path.endsWith(".zip")) {
loopUnzip(is, level + 1, basePath + "/" + path, loopCallBack);
}
});
} /**
* 解压zip,必须是zip结尾的文件(错误属性的文件会被排除,因为不排除java也解压不了)
*
* @param inputStream 初始输入流
* @param callBack 回调
* @throws IOException io异常
*/
public static void decompress(InputStream inputStream, CallBack callBack) throws IOException {
try (NoCloseBufferStream bufferedInputStream = new NoCloseBufferStream(inputStream);
ZipArchiveInputStream zipInputStream = new ZipArchiveInputStream(bufferedInputStream, CharsetUtil.defaultCharset().name(), true, true)) {
decompress(zipInputStream, callBack);
}
} public static void decompress(byte[] bytes, CallBack callBack) throws IOException {
try (ByteArrayInputStream inputStream = IoUtil.toStream(bytes);) {
bytes = null;
decompress(inputStream, callBack);
}
} private static void decompress(ZipArchiveInputStream inputStream, CallBack callBack) throws IOException {
ZipArchiveEntry nextEntry = inputStream.getNextZipEntry();
while (nextEntry != null) {
final String name = nextEntry.getName();
//过滤无用文件
if (!name.startsWith("__MACOSX") && !name.contains(".DS_Store") && !name.contains("Thumbs.db") && !name.startsWith("._")) {
if (!nextEntry.isDirectory()) {
callBack.call(name, new NoCloseBufferStream(inputStream));
}
}
nextEntry = inputStream.getNextZipEntry();
}
} @FunctionalInterface
public static interface CallBack {
void call(String relativePath, InputStream is) throws IOException;
} @FunctionalInterface
public static interface LoopCallBack {
boolean call(int level, String relativePath, String basePath, InputStream is) throws IOException;
} }

java多层级zip解压的更多相关文章

  1. JAVA zip解压 MALFORMED 错误

    最近在在使用zip 解压时,使用JDK1.7及以上版本在解压时,某些文件会报异常 Exception in thread "main" java.lang.IllegalArgum ...

  2. Java zip解压,并遍历zip中的配置文件 .cfg或.properties

    1.解析cfg或properties配置文件 讲配置文件,读取,并封装成为map类型数据 /** * 解析cfg文件 * * @param cfgFile * @return */ public st ...

  3. windows下tomcat zip解压版安装方法

    下面记录一下在win7(32位)系统下,安装zip解压版的方法: 一.下载zip压缩包 地址:http://tomcat.apache.org/download-80.cgi 二.解压 我把解压包解压 ...

  4. CentOS7下zip解压和unzip压缩文件

    1.安装zip.unzip应用. yum install zip unzip

  5. MySQL For Windows Zip解压版安装

    前言 Windows 下 MySQL 有msi和zip解压安装版两种,而zip版只需解压并做简单配置后就能使用,我个人比较喜欢这种方式. 注意我们这里说的MySQL是指MySQL服务器,有很多初学的同 ...

  6. 解决ubuntu中zip解压的中文乱码问题

    转自解决ubuntu中zip解压的中文乱码问题 在我的ubuntu12.10中,发现显示中文基本都是正常的,只有在解压windows传过来的zip文件时,才会出现乱码.所以,我用另一个方法解决中文乱码 ...

  7. 【转载】在linux下别用zip 用tar来压缩文件 zip解压后还是utf-8 window10是GBK

    3.2 使用 unzip 命令解压缩 zip 文件 将 shiyanlou.zip 解压到当前目录:   $ unzip shiyanlou.zip 使用安静模式,将文件解压到指定目录:   $ un ...

  8. ubuntu zip解压

    您好,zip xx.zip压缩,unzip xx.zip 解压,tar zcvf xx.tar.gz压缩tar zxvf xx.tar.gz解压

  9. zip 解压脚本

    zip 解压脚本 gpk-unzip.py #!/usr/bin/env python # -*- coding: utf-8 -*- # unzip-gbk.py import os import ...

  10. mysql5.5.x.zip 解压版安装教程

    一,前言 记一次安装解压版的mysql 5.5的经过,参考了一些文章,也遇到了一些错误,最终都安装成功了.在这里记录一下安装的过程,一方面自己做一个记录,领一方面给大家提供一份参考. 二,环境 1,w ...

随机推荐

  1. kali安装和升级

    实验介绍: kali集成了世界上所有优秀的渗透测试工具 一:在VMware上安装 这里只详细介绍kali在VMware的安装,u盘和物理机上的安装不做详解 在kali官网下载kali镜像iso文件 下 ...

  2. C++中指针和数组相关的运算符优先级

    概述 本文深入介绍了与指针和数组相关的运算符优先级,利用代码示例展示了当左结合和右结合运算符同时存在时的结合方式,同时也演示了如何使用()来强制人为指定结合顺序. 指针.数组相关的运算符优先级 下表展 ...

  3. USB协议详解第11讲(USB描述符-总结)

    描述符回顾总结 1.其实所有的描述符都是USB设备用来描述自己属性及用途的,所以必须在设备端实现对应的描述符,主机会在枚举此设备的时候根据设备实现的描述符去确定设备到底是一个什么样的设备.设备需要的总 ...

  4. 数据库周刊54丨2020 年度报告:PingCAP、腾讯云数据库、人大金仓、GoldenDB ;CPU 100% SQL优化案例;Mysql内存溢出处理;sql server PK openGauss;Oracle 巡检说明书;避免删库跑路黑天鹅……

    热门资讯 1.PingCAP 2020 年度报告|相信开放的力量 [摘要]本文为PingCAP 2020年度报告.盘点了PingCAP里程碑大事件:完成D轮2.7亿美元融资,创造全球数据库历史新的里程 ...

  5. jenkins拉取git https报错

    报错内容 解决方式 在Jenkins服务器执行命令 git config --global http.sslVerify false

  6. 你在使用 KubeSphere 吗?

    如果你正在使用 KubeSphere,欢迎在社区分享你的使用和实践经验,赢取 KubeSphere 周边礼品(T恤.帆布袋.徽章等)以及 Kubernetes 技术书籍. 为什么我们要征集用户案例? ...

  7. KubeSphere 社区双周报 | OpenFunction v1.0.0 发布 | 2023.03.03-03.16

    KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...

  8. 相机系统 GLFW OPENGL

    目录 0. 前言 1. 世界坐标系 2. GLFW 窗口坐标系 与 坐标系变换 3. 相机是什么东西 4. 相机的平面位移(上下左右) 5. 相机的聚焦点环绕(球形环绕 ArcBall Orbit) ...

  9. WebUploader 文件上传,兼容ios和安卓

    var upImg = WebUploader.create({ auto: true, swf: 'webuploader-0.1.5/Uploader.swf', // 图片接收服务端. serv ...

  10. MarkDown用法学习笔记

    标题: 用 '#'标识,可以到从1到6级标题设置,有多少个'#'符号就对应多少级标题 粗体: 用''标识,如果两边只有一个''标识是斜体,如果两有2个这符号标题是加粗,如果有3个这符号标识是斜体和加粗 ...