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. 五行强度得分_喜用神api免费接口_json数据八字五行强弱接口

    本API接口基于深厚的八字学原理,为用户提供详尽的五行(金.木.水.火.土)强弱分析.五行打分评估,以及精准的喜用神判断.用户只需输入自己的八字信息,即可获得全面而深入的命理解读. ‌一.核心功能‌ ...

  2. 鸿蒙NEXT开发声明式UI是咋回事?

    大家好,我是 V 哥,ArkTS 是 HarmonyOS 优选的主力应用开发语言,它在 TypeScript 的基础上进行了扩展,提供了声明式 UI 描述.自定义组件和动态扩展 UI 元素的能力.这些 ...

  3. KubeSphere 网关的设计与实现(解读)

    作者:泓舟子,KubeSphere 后端研发工程师,云原生爱好者,现专注于云原生微服务方向. KubeSphere 中为什么需要网关? 如果需要将 K8s 集群内的服务暴露到外部访问有那些方式呢?可以 ...

  4. KubeSphere DevOps 流水线入门指南

    作者:赵海亮,浙江大学计算机专业四年级在读博士生,研究方向为云计算.边缘计算.分布式系统等. 虽然 KubeSphere 能够将我们从 yaml 文件的编写中解放出来,但是项目上云仍然十分繁琐. 此外 ...

  5. 配置与美化Linux桌面

    本文讲述安装了Kali Linux 2024.3,Gnome桌面,以及安装各种应用与美化的过程. 安装操作系统 网络上下载操作系统镜像,写入u盘,制作启动盘 https://mirrors.tuna. ...

  6. HTB打靶记录-Infiltrator

    nmap scan nmap -A 10.10.11.31 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-15 13:18 CST Nma ...

  7. 使用MySQL Workbench进行数据库备份

    1.打开MySQL Workbench 2.进行数据库连接配置 如果之前连过,会有历史记录,直接点击需要备份的连接即可 3.进入主界面后,选择左侧的Administration选项卡,然后点击Data ...

  8. Flask常用插件

    Flask特点: 1.小而精的代表 2.基于Werkzeug工具箱编写的轻量级web开发框架,它主要面向需求简单,项目周期短的Web小应用 3.灵活,核心思想是Flask只完成基本的功能,别的功能都是 ...

  9. Git命令缩写

    g = 'git' ga = 'git add' gaa='git add --all' gapa='git add --patch' gb='git branch' gba='git branch ...

  10. 浅析Mongodb注入

    前言 不太会Mongodb的用法,这里学习一下 简单介绍 Mongodb是非关系型数据库(NoSQL),在 MySQL 中,我们所熟知的几个最常见的概念是数据库 (Database).表 (Table ...