java多层级zip解压
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解压的更多相关文章
- JAVA zip解压 MALFORMED 错误
最近在在使用zip 解压时,使用JDK1.7及以上版本在解压时,某些文件会报异常 Exception in thread "main" java.lang.IllegalArgum ...
- Java zip解压,并遍历zip中的配置文件 .cfg或.properties
1.解析cfg或properties配置文件 讲配置文件,读取,并封装成为map类型数据 /** * 解析cfg文件 * * @param cfgFile * @return */ public st ...
- windows下tomcat zip解压版安装方法
下面记录一下在win7(32位)系统下,安装zip解压版的方法: 一.下载zip压缩包 地址:http://tomcat.apache.org/download-80.cgi 二.解压 我把解压包解压 ...
- CentOS7下zip解压和unzip压缩文件
1.安装zip.unzip应用. yum install zip unzip
- MySQL For Windows Zip解压版安装
前言 Windows 下 MySQL 有msi和zip解压安装版两种,而zip版只需解压并做简单配置后就能使用,我个人比较喜欢这种方式. 注意我们这里说的MySQL是指MySQL服务器,有很多初学的同 ...
- 解决ubuntu中zip解压的中文乱码问题
转自解决ubuntu中zip解压的中文乱码问题 在我的ubuntu12.10中,发现显示中文基本都是正常的,只有在解压windows传过来的zip文件时,才会出现乱码.所以,我用另一个方法解决中文乱码 ...
- 【转载】在linux下别用zip 用tar来压缩文件 zip解压后还是utf-8 window10是GBK
3.2 使用 unzip 命令解压缩 zip 文件 将 shiyanlou.zip 解压到当前目录: $ unzip shiyanlou.zip 使用安静模式,将文件解压到指定目录: $ un ...
- ubuntu zip解压
您好,zip xx.zip压缩,unzip xx.zip 解压,tar zcvf xx.tar.gz压缩tar zxvf xx.tar.gz解压
- zip 解压脚本
zip 解压脚本 gpk-unzip.py #!/usr/bin/env python # -*- coding: utf-8 -*- # unzip-gbk.py import os import ...
- mysql5.5.x.zip 解压版安装教程
一,前言 记一次安装解压版的mysql 5.5的经过,参考了一些文章,也遇到了一些错误,最终都安装成功了.在这里记录一下安装的过程,一方面自己做一个记录,领一方面给大家提供一份参考. 二,环境 1,w ...
随机推荐
- Android Systrace 基础知识 -- 分析 Systrace 预备知识
1. 正文 1.1 线程状态查看 Systrace 会用不同的颜色来标识不同的线程状态, 在每个方法上面都会有对应的线程状态来标识目前线程所处的状态,通过查看线程状态我们可以知道目前的瓶颈是什么, 是 ...
- getshell后的基本信息收集
基本信息收集 系统类型判断 使用whoami能快速判断系统是Linux还是Windows. 如果是Windows, 使用命令systeminfo | findstr OS可得到WIndows版本. 使 ...
- 还在使用昂贵的虚拟机?来试试 Devbox,便宜 6 倍!
这篇小短文来介绍一下用虚拟机的场景是怎么被 Devbox 全方位碾压的. Devbox 唯一弱点是公网出口的地方不分配独立的 IP 地址,但是这对我们绝大多数场景是没有影响的,通过域名和端口访问我们的 ...
- KubeSphere 社区双周报|2024.06.21-07.04
KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...
- KubeSphere 3.2.1 正式发布,多项功能优化来袭!
KubeSphere 从诞生第一天起就 100% 开源,并以社区的方式成长,在各位社区小伙伴的共同努力下,KubeSphere 迅速走向全球,成为全世界最受欢迎的开源容器平台之一. 经过 3 年的发展 ...
- Ubuntu 22.04 全局快捷键失效问题
安装完 Ubuntu 22.04 后,你有可能会发现系统的快捷键失效了.侧栏用 Win + x 选中程序不可用了.为各种应用程序设置的快捷键也不起作用了. 出现此现象的原因,是因为 Ubuntu 22 ...
- 【多图】2022年7月的WSA安装教程
wsa是微软推出的一款的安卓虚拟机,尚在测试中. 首先翻看微软文档,安装wsa只需要在微软商店里安装 Amazon Store 即可,打开商店搜索,根本搜不到: 这是因为 Amazon Store 仅 ...
- ROS入门21讲(3)
七.话题消息的定义和使用 目的:实现Publisher 与 Subscriber 之间的传输 1.自定义话题消息 如何自定义话题消息? ①完成数据接口的定义---定义msg文件 Person.msg ...
- 深度解读GaussDB逻辑解码技术原理
本文分享自华为云社区<[GaussTech技术专栏]GaussDB逻辑解码技术原理>,作者:GaussDB 数据库. 1.背景 随着国内各大行业数字化改造步伐的加快,异构数据库数据同步的需 ...
- php日志分割
为了方便查看php错误日志信息,将php的日志按照时间进行分割,器脚本如下 phpPid='/usr/local/webserver/php-5.3.27/var/run/php-fpm.pid' p ...