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. USB编码方式(NRZI)及时钟同步方式

    1.概述 在同步通讯系统中,两个设备通讯则需要同步信号,同步信号分为时钟同步信号和自同步信号两种,时钟同步方式在通讯链路上具有时钟信号(IIC.SPI),自同步方式在通讯链路中没有同步信号(PCIE. ...

  2. 【ZROJ2730】简单题 可持久化分块题解

    Description 给定一棵 \(n\) 个节点的树,每次询问编号为 \([l, r]\) 的点中有多少个是祖先关系. \(n, q \le 10^5\). Solution 直接做的话树上的祖先 ...

  3. 3DRealCar: An In-the-wild RGB-D Car Dataset with 360-degree Views

    3DRealCar:An In-the-wild RGB-D Car Dataset with 360-degree Views Du, Xiaobiao and Sun, Haiyang and W ...

  4. Notification Manager 2.0.0 发布:新增飞书通知、通知路由、通知静默

    Notification Manager 是 KubeSphere 可观测团队开源的一款 Kubernetes 平台上的多租户通知管理系统,其从 Kubernetes 接收告警.事件.审计,根据用户设 ...

  5. 什么是 Nodejs

    这集来聊什么是 Nodejs ,看看 Node.js 是为了解决什么样的痛点而生的,为啥说它是一个 JS 的运行环境,以及 npm 是什么,为何能引发了 Web 开发的革命. Node.js 的诞生 ...

  6. WPF学习-布局

    1.  Grid布局 ,(Table 布局) 两行两列布局, Border  0 行 0 列默认开始 <Window x:Class="WpfApp.MainWindow" ...

  7. chapter4 quantum circuits

    本章内容为 P172--P215: 主机 word 文件为: chapter4.docx 详情见文件 chapter4.1_singlequbit.cdf  或主机同名文件 4.7 Simulatio ...

  8. 关于MNN工程框架编译出来的静态库和动态库的使用

    一.MNN.lib文件路径 如果你看过之前的博客内容,应该可以在编译的的工程当中 C:\Users\Administrator\Desktop\MNN\MNN-master\MNN-CPU-OPENC ...

  9. 一文搞懂 ARM 64 系列: PACISB

    1 PAC AMR64提供了PAC(Pointer Authentication Code)机制. 所谓PAC,简单来说就是使用存储在芯片硬件上的「密钥」,一个「上下文」,与「指针地址」进行加密计算, ...

  10. CodeForces - 1398C Good Subarrays

    CodeForces - 1398C 挺简单的题目,但是没有想到还是整理一下 方法1 把每个元素都减1,那么满足题意的就是一段和的值是0,然后维护前缀和,如果发现这个前缀和之前出现过,就说明有满足题意 ...