Java實(shí)現(xiàn)解壓zip壓縮包的兩種方法(支持多層級)
前言
當(dāng)我們需要上傳大量文件時(shí),壓縮文件可以大大減少傳輸時(shí)間和網(wǎng)絡(luò)帶寬,在Java中提供了壓縮和解壓縮文件的功能,可以使用java.util.zip包中的類來實(shí)現(xiàn)。但是也有很多不足, 本篇將對如何使用 Java 實(shí)現(xiàn)解壓縮進(jìn)行簡單總結(jié)。
ZIP:最常見的壓縮文件格式之一,可以存儲一個(gè)或多個(gè)文件,并可在不同的操作系統(tǒng)中進(jìn)行解壓縮。
一、使用ZipInputStream解壓文件流(不支持中文)
public static List<File> unzipInputStream(InputStream zipInputStream) {
List<File> fileList = new ArrayList<>();
try (ZipInputStream zip = new ZipInputStream(zipInputStream)) {
ZipEntry zipEntry = null;
while ((zipEntry = zip.getNextEntry()) != null) {
String fileName_zip = zipEntry.getName();
File file = new File(fileName_zip);
if (fileName_zip.endsWith("/")) {
file.mkdir();
continue;
} else {
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
byte[] byte_s = new byte[1024];
int num;
while ((num = zip.read(byte_s, 0, byte_s.length)) > 0) {
outputStream.write(byte_s, 0, num);
}
outputStream.close();
}
fileList.add(file);
}
} catch (Exception e) {
e.printStackTrace();
}
return fileList;
}
在調(diào)用JDK自帶的zipfile讀取壓縮包文件的時(shí)候,出現(xiàn)了以下錯(cuò)誤: MALFORMED
java.lang.IllegalArgumentException: MALFORMED
at java.util.zip.ZipCoder.toString(ZipCoder.java:58)
at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:300)
at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:122)
at com.wonder.meta.util.ZipUtils.unzipInputStream(ZipUtils.java:26)
1.1 原因描述
后來經(jīng)過檢查,發(fā)現(xiàn)壓縮包內(nèi)有一個(gè)文件的名字帶有中文,解析壓縮包中,讀取中文文件導(dǎo)致報(bào)錯(cuò)
由于操作系統(tǒng)平臺的差異,導(dǎo)致zip壓縮包的編碼格式不同,windows默認(rèn)使用GB2312格式,mac和linux默認(rèn)使用utf-8格式,造成這種現(xiàn)象的原因有幾種可能:
- 壓縮包中包含中文
- 在linux上壓縮,在windows上使用解壓工具解壓
- 使用jdk api直接解壓
1.2 解決方案
推薦使用(經(jīng)過測試)Apache commons-compress 工具包解決跨平臺編碼問題
二、使用ZipArchiveInputStream解壓(推薦)
2.1 引入pom依賴
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.21</version>
</dependency>
ZipInputStream 和 ZipArchiveInputStream 都是 Java 中用于處理 Zip 文件的類,但是它們之間有一些區(qū)別。
ZipInputStream 是 Java 標(biāo)準(zhǔn)庫中提供的類,而 ZipArchiveInputStream 是 Apache Commons Compress 庫中提供的類。
ZipInputStream 只能讀取普通的 Zip 文件,而 ZipArchiveInputStream 支持讀取多種壓縮格式,包括 Zip、Gzip、Tar、Jar 等。
ZipArchiveInputStream 提供了更多的選項(xiàng)和功能,例如可以設(shè)置編碼方式、支持密碼保護(hù)的 Zip 文件等。
ZipArchiveInputStream 的性能比 ZipInputStream 更好,在處理大型 Zip 文件時(shí)表現(xiàn)更出色。
2.2 進(jìn)行改造后
public static List<File> unzipInputStream(InputStream zipInputStream) {
List<File> fileList = new ArrayList<>();
try (ZipArchiveInputStream zip = new ZipArchiveInputStream(zipInputStream)) {
ZipArchiveEntry zipEntry = null;
while ((zipEntry = zip.getNextZipEntry()) != null) {
String fileName_zip = zipEntry.getName();
File file = new File(fileName_zip);
if (fileName_zip.endsWith("/")) {
file.mkdir();
continue;
} else {
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
byte[] byte_s = new byte[1024];
int num;
while ((num = zip.read(byte_s, 0, byte_s.length)) > 0) {
outputStream.write(byte_s, 0, num);
}
outputStream.close();
}
fileList.add(file);
}
} catch (Exception e) {
e.printStackTrace();
}
return fileList;
}
測試正常
三、整理為工具類
- 包含獲取目錄下的圖片…(包括子目錄)
- 定義文件過濾器(過濾想留下的文件)
3.1 ZipUtils
public class ZipUtils {
public static List<File> unzipInputStream(InputStream zipInputStream) {
List<File> fileList = new ArrayList<>();
try (ZipArchiveInputStream zip = new ZipArchiveInputStream(zipInputStream)) {
ZipArchiveEntry zipEntry = null;
while ((zipEntry = zip.getNextZipEntry()) != null) {
String fileName_zip = zipEntry.getName();
File file = new File(fileName_zip);
if (fileName_zip.endsWith("/")) {
file.mkdir();
continue;
} else {
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
byte[] byte_s = new byte[1024];
int num;
while ((num = zip.read(byte_s, 0, byte_s.length)) > 0) {
outputStream.write(byte_s, 0, num);
}
outputStream.close();
}
fileList.add(file);
}
} catch (Exception e) {
e.printStackTrace();
}
return fileList;
}
// 單獨(dú)列出方法獲取目錄下的圖片
public static List<File> listAll(File parent) {
List<File> fileList = new ArrayList<>();
MyFilter myFilter = new MyFilter();
File[] children = parent.listFiles(myFilter);
if(children != null){
for (int i = 0; i < children.length; i++) {
// 如果子文件是個(gè)文件夾,則遞歸調(diào)用
if (!children[i].isFile()) {
listAll(children[i]);
} else {
fileList.add(children[i]);
}
}
}
return fileList;
}
//定義文件過濾器
static class MyFilter implements FilenameFilter {
@Override
public boolean accept(File dir, String name) {
return name.contains(".png") || dir.isDirectory();
}
}
}
3.2 這里列出實(shí)現(xiàn)類的方法作為參考
記得刪除臨時(shí)文件
@Override
public void batchUploadSign(MultipartFile multipartFile) {
List<File> fileList = null;
try {
fileList = ZipUtils.unzipInputStream(multipartFile.getInputStream());
//fileList可能存在目錄
for (File fileTemp : fileList) {
List<File> fileTempList = ZipUtils.listAll(fileTemp);
if (CollectionUtil.isNotEmpty(fileTempList)) {
fileList.addAll(fileTempList);
}
}
if (CollectionUtil.isNotEmpty(fileList)) {
log.info("省略業(yè)務(wù)邏輯");
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
//刪除臨時(shí)文件
if (null != fileList) {
for (File file1 : fileList) {
file1.delete();
}
}
}
}到此這篇關(guān)于Java實(shí)現(xiàn)解壓zip壓縮包的兩種方法(支持多層級)的文章就介紹到這了,更多相關(guān)Java 解壓zip壓縮包內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java壓縮zip文件中文亂碼問題解決方法
- java使用gzip實(shí)現(xiàn)文件解壓縮示例
- Java解壓和壓縮帶密碼的zip文件過程詳解
- Java后臺實(shí)現(xiàn)瀏覽器一鍵導(dǎo)出下載zip壓縮包
- Java多文件以ZIP壓縮包導(dǎo)出的實(shí)現(xiàn)方法
- 用Java進(jìn)行zip文件壓縮與解壓縮
- Java實(shí)現(xiàn)導(dǎo)出ZIP壓縮包的方法
- java實(shí)現(xiàn)一次性壓縮多個(gè)文件到zip中的方法示例
- Java創(chuàng)建ZIP壓縮文件的方法
- Java實(shí)現(xiàn)文件壓縮為zip和解壓zip壓縮包
- 淺談Java?Zip?壓縮及其優(yōu)化
相關(guān)文章
基于springBoot配置文件properties和yml中數(shù)組的寫法
這篇文章主要介紹了springBoot配置文件properties和yml中數(shù)組的寫法,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
java 域?qū)ο蠊蚕頂?shù)據(jù)的實(shí)現(xiàn)
本文主要介紹了java 域?qū)ο蠊蚕頂?shù)據(jù)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03
詳解Mybatis逆向工程中使用Mysql8.0版本驅(qū)動遇到的問題
今天在使用 8.0.12 版的 mysql 驅(qū)動時(shí)遇到了各種各樣的坑。這篇文章主要介紹了詳解Mybatis逆向工程中使用Mysql8.0版本驅(qū)動遇到的問題,感興趣的小伙伴們可以參考一下2018-10-10
@TransactionalEventListener的使用和實(shí)現(xiàn)原理分析
這篇文章主要介紹了@TransactionalEventListener的使用和實(shí)現(xiàn)原理分析,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Java中Caffeine本地緩存項(xiàng)目實(shí)例
這篇文章主要介紹了Java中Caffeine本地緩存項(xiàng)目實(shí)例,Caffeine是一個(gè)高性能Java 緩存庫,使用Java8對Guava緩存重寫版本,在Spring Boot 2.0中將取代Guava,使用spring.cache.cache-names屬性可以在啟動時(shí)創(chuàng)建緩存,需要的朋友可以參考下2023-10-10
SpringBoot同時(shí)集成Mybatis和Mybatis-plus框架
在實(shí)際開發(fā)中,項(xiàng)目里面一般都是Mybatis和Mybatis-Plus公用,但是公用有版本不兼容的問題,本文主要介紹了Spring Boot項(xiàng)目中同時(shí)集成Mybatis和Mybatis-plus,具有一檔的參考價(jià)值,感興趣的可以了解一下2024-12-12
mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限項(xiàng)目實(shí)踐
本文主要介紹了mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06

