Java對(duì)zip,rar,7z文件帶密碼解壓實(shí)例詳解
前言
在一些日常業(yè)務(wù)中,會(huì)遇到一些瑣碎文件需要統(tǒng)一打包到一個(gè)壓縮包中上傳,業(yè)務(wù)方在后臺(tái)接收到壓縮包后自行解壓,然后解析相應(yīng)文件。而且可能涉及安全保密,因此會(huì)在壓縮時(shí)帶上密碼,要求后臺(tái)業(yè)務(wù)可以指定密碼進(jìn)行解壓。
應(yīng)用環(huán)境說(shuō)明:jdk1.8,maven3.x,需要基于java語(yǔ)言實(shí)現(xiàn)對(duì)zip、rar、7z等常見(jiàn)壓縮包的解壓工作。
首先關(guān)于zip和rar、7z等壓縮工具和壓縮算法就不在此贅述,下面通過(guò)一個(gè)數(shù)據(jù)對(duì)比,使用上述三種不同的壓縮算法,采用默認(rèn)的壓縮方式,看到壓縮的文件大小如下:

轉(zhuǎn)換成圖表看得更直觀,如下圖:

從以上圖表可以看到,7z的壓縮率是最高,而zip壓縮率比較低,rar比zip稍微好點(diǎn)。單純從壓縮率看,7z>rar4>rar5>zip。
實(shí)現(xiàn)代碼
下面具體說(shuō)明在java中如何進(jìn)行相應(yīng)解壓:
1、pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yelang</groupId>
<artifactId>7zdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>net.sf.sevenzipjbinding</groupId>
<artifactId>sevenzipjbinding</artifactId>
<version>16.02-2.01</version>
</dependency>
<dependency>
<groupId>net.sf.sevenzipjbinding</groupId>
<artifactId>sevenzipjbinding-all-platforms</artifactId>
<version>16.02-2.01</version>
</dependency>
<dependency>
<groupId>org.tukaani</groupId>
<artifactId>xz</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/xdocreport -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>xdocreport</artifactId>
<version>1.0.6</version>
</dependency>
</dependencies>
</project>
主要依賴的jar包有:zip4j、sevenzipjbinding等。
2、zip解壓
@SuppressWarnings("resource")
private static String unZip(String rootPath, String sourceRarPath, String destDirPath, String passWord) {
ZipFile zipFile = null;
String result = "";
try {
//String filePath = sourceRarPath;
String filePath = rootPath + sourceRarPath;
if (StringUtils.isNotBlank(passWord)) {
zipFile = new ZipFile(filePath, passWord.toCharArray());
} else {
zipFile = new ZipFile(filePath);
}
zipFile.setCharset(Charset.forName("GBK"));
zipFile.extractAll(rootPath + destDirPath);
} catch (Exception e) {
log.error("unZip error", e);
return e.getMessage();
}
return result;
}
3、rar解壓
private static String unRar(String rootPath, String sourceRarPath, String destDirPath, String passWord) {
String rarDir = rootPath + sourceRarPath;
String outDir = rootPath + destDirPath + File.separator;
RandomAccessFile randomAccessFile = null;
IInArchive inArchive = null;
try {
// 第一個(gè)參數(shù)是需要解壓的壓縮包路徑,第二個(gè)參數(shù)參考JdkAPI文檔的RandomAccessFile
randomAccessFile = new RandomAccessFile(rarDir, "r");
if (StringUtils.isNotBlank(passWord))
inArchive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile), passWord);
else
inArchive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile));
ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();
for (final ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
final int[] hash = new int[]{0};
if (!item.isFolder()) {
ExtractOperationResult result;
final long[] sizeArray = new long[1];
File outFile = new File(outDir + item.getPath());
File parent = outFile.getParentFile();
if ((!parent.exists()) && (!parent.mkdirs())) {
continue;
}
if (StringUtils.isNotBlank(passWord)) {
result = item.extractSlow(data -> {
try {
IOUtils.write(data, new FileOutputStream(outFile, true));
} catch (Exception e) {
e.printStackTrace();
}
hash[0] ^= Arrays.hashCode(data); // Consume data
sizeArray[0] += data.length;
return data.length; // Return amount of consumed
}, passWord);
} else {
result = item.extractSlow(data -> {
try {
IOUtils.write(data, new FileOutputStream(outFile, true));
} catch (Exception e) {
e.printStackTrace();
}
hash[0] ^= Arrays.hashCode(data); // Consume data
sizeArray[0] += data.length;
return data.length; // Return amount of consumed
});
}
if (result == ExtractOperationResult.OK) {
log.error("解壓rar成功...." + String.format("%9X | %10s | %s", hash[0], sizeArray[0], item.getPath()));
} else if (StringUtils.isNotBlank(passWord)) {
log.error("解壓rar成功:密碼錯(cuò)誤或者其他錯(cuò)誤...." + result);
return "password";
} else {
return "rar error";
}
}
}
} catch (Exception e) {
log.error("unRar error", e);
return e.getMessage();
} finally {
try {
inArchive.close();
randomAccessFile.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return "";
}
4、7z解壓
private static String un7z(String rootPath, String sourceRarPath, String destDirPath, String passWord) {
try {
File srcFile = new File(rootPath + sourceRarPath);//獲取當(dāng)前壓縮文件
// 判斷源文件是否存在
if (!srcFile.exists()) {
throw new Exception(srcFile.getPath() + "所指文件不存在");
}
//開(kāi)始解壓
SevenZFile zIn = null;
if (StringUtils.isNotBlank(passWord)) {
zIn = new SevenZFile(srcFile, passWord.toCharArray());
} else {
zIn = new SevenZFile(srcFile);
}
SevenZArchiveEntry entry = null;
File file = null;
while ((entry = zIn.getNextEntry()) != null) {
if (!entry.isDirectory()) {
file = new File(rootPath + destDirPath, entry.getName());
if (!file.exists()) {
new File(file.getParent()).mkdirs();//創(chuàng)建此文件的上級(jí)目錄
}
OutputStream out = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(out);
int len = -1;
byte[] buf = new byte[1024];
while ((len = zIn.read(buf)) != -1) {
bos.write(buf, 0, len);
}
// 關(guān)流順序,先打開(kāi)的后關(guān)閉
bos.close();
out.close();
}
}
} catch (Exception e) {
log.error("un7z is error", e);
return e.getMessage();
}
return "";
}
5、解壓統(tǒng)一入口封裝
public static Map<String,Object> unFile(String rootPath, String sourcePath, String destDirPath, String passWord) {
Map<String,Object> resultMap = new HashMap<String, Object>();
String result = "";
if (sourcePath.toLowerCase().endsWith(".zip")) {
//Wrong password!
result = unZip(rootPath, sourcePath, destDirPath, passWord);
} else if (sourcePath.toLowerCase().endsWith(".rar")) {
//java.security.InvalidAlgorithmParameterException: password should be specified
result = unRar(rootPath, sourcePath, destDirPath, passWord);
System.out.println(result);
} else if (sourcePath.toLowerCase().endsWith(".7z")) {
//PasswordRequiredException: Cannot read encrypted content from G:\ziptest\11111111.7z without a password
result = un7z(rootPath, sourcePath, destDirPath, passWord);
}
resultMap.put("resultMsg", 1);
if (StringUtils.isNotBlank(result)) {
if (result.contains("password")) resultMap.put("resultMsg", 2);
if (!result.contains("password")) resultMap.put("resultMsg", 3);
}
resultMap.put("files", null);
//System.out.println(result + "==============");
return resultMap;
}
6、測(cè)試代碼
Long start = System.currentTimeMillis();
unFile("D:/rarfetch0628/","apache-tomcat-8.5.69.zip","apache-tomcat-zip","222");
long end = System.currentTimeMillis();
System.out.println("zip解壓耗時(shí)==" + (end - start) + "毫秒");
System.out.println("============================================================");
Long rar4start = System.currentTimeMillis();
unFile("D:/rarfetch0628/","apache-tomcat-8.5.69-4.rar","apache-tomcat-rar4","222");
long rar4end = System.currentTimeMillis();
System.out.println("rar4解壓耗時(shí)==" + (rar4end - rar4start)+ "毫秒");
System.out.println("============================================================");
Long rar5start = System.currentTimeMillis();
unFile("D:/rarfetch0628/","apache-tomcat-8.5.69-5.rar","apache-tomcat-rar5","222");
long rar5end = System.currentTimeMillis();
System.out.println("rar5解壓耗時(shí)==" + (rar5end - rar5start)+ "毫秒");
System.out.println("============================================================");
Long zstart = System.currentTimeMillis();
unFile("D:/rarfetch0628/","apache-tomcat-8.5.69.7z","apache-tomcat-7z","222");
long zend = System.currentTimeMillis();
System.out.println("7z解壓耗時(shí)==" + (zend - zstart)+ "毫秒");
System.out.println("============================================================");
在控制臺(tái)中可以看到以下結(jié)果:


總結(jié):本文采用java語(yǔ)言實(shí)現(xiàn)了對(duì)zip和rar、7z文件的解壓統(tǒng)一算法。并對(duì)比了相應(yīng)的解壓速度,支持傳入密碼進(jìn)行在線解壓。
本文參考代碼在補(bǔ)充內(nèi)容里,不過(guò)代碼直接運(yùn)行有問(wèn)題,這里進(jìn)行了調(diào)整,主要優(yōu)化的點(diǎn)如下:
1、pom.xml 遺漏了slf4j、commons-lang3、xdocreport等依賴
2、zip路徑優(yōu)化
3、去掉一些無(wú)用信息
4、優(yōu)化異常信息
補(bǔ)充
1.maven引用
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>net.sf.sevenzipjbinding</groupId>
<artifactId>sevenzipjbinding</artifactId>
<version>16.02-2.01</version>
</dependency>
<dependency>
<groupId>net.sf.sevenzipjbinding</groupId>
<artifactId>sevenzipjbinding-all-platforms</artifactId>
<version>16.02-2.01</version>
</dependency>
<dependency>
<groupId>org.tukaani</groupId>
<artifactId>xz</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.21</version>
</dependency>
2.實(shí)現(xiàn)代碼如下
import fr.opensagres.xdocreport.core.io.IOUtils;
import net.lingala.zip4j.ZipFile;
import net.sf.sevenzipjbinding.*;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.*;
public class ZipAndRarTools {
private static final Logger log = LoggerFactory.getLogger(ZipAndRarTools.class);
/*
解壓zip
*/
private static String unZip(String rootPath, String sourceRarPath, String destDirPath, String passWord) {
ZipFile zipFile = null;
try {
if (StringUtils.isNotBlank(passWord)) {
zipFile = new ZipFile(filePath, passWord.toCharArray());
} else {
zipFile = new ZipFile(filePath);
}
zipFile.extractAll(rootPath + destDirPath);
} catch (Exception e) {
log.error("unZip error", e);
return e.getMessage();
}
return "";
}
/*
解壓rar rar5
*/
private static String unRar(String rootPath, String sourceRarPath, String destDirPath, String passWord) {
/*final File rar = new File(rootPath + sourceRarPath);
final File destinationFolder = new File(rootPath + destDirPath);
destinationFolder.mkdir();
try {
Junrar.extract(rar, destinationFolder);
} catch (Exception e) {
log.error("unRar error", e);
return e.getMessage();
}*/
String rarDir = rootPath + sourceRarPath;
String outDir = rootPath + destDirPath + File.separator;
RandomAccessFile randomAccessFile = null;
IInArchive inArchive = null;
try {
// 第一個(gè)參數(shù)是需要解壓的壓縮包路徑,第二個(gè)參數(shù)參考JdkAPI文檔的RandomAccessFile
randomAccessFile = new RandomAccessFile(rarDir, "r");
if (StringUtils.isNotBlank(passWord))
inArchive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile), passWord);
else
inArchive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile));
ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();
for (final ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
final int[] hash = new int[]{0};
if (!item.isFolder()) {
ExtractOperationResult result;
final long[] sizeArray = new long[1];
File outFile = new File(outDir + item.getPath());
File parent = outFile.getParentFile();
if ((!parent.exists()) && (!parent.mkdirs())) {
continue;
}
if (StringUtils.isNotBlank(passWord)) {
result = item.extractSlow(data -> {
try {
IOUtils.write(data, new FileOutputStream(outFile, true));
} catch (Exception e) {
e.printStackTrace();
}
hash[0] ^= Arrays.hashCode(data); // Consume data
sizeArray[0] += data.length;
return data.length; // Return amount of consumed
}, passWord);
} else {
result = item.extractSlow(data -> {
try {
IOUtils.write(data, new FileOutputStream(outFile, true));
} catch (Exception e) {
e.printStackTrace();
}
hash[0] ^= Arrays.hashCode(data); // Consume data
sizeArray[0] += data.length;
return data.length; // Return amount of consumed
});
}
if (result == ExtractOperationResult.OK) {
log.error("解壓rar成功...." + String.format("%9X | %10s | %s", hash[0], sizeArray[0], item.getPath()));
} else if (StringUtils.isNotBlank(passWord)) {
log.error("解壓rar成功:密碼錯(cuò)誤或者其他錯(cuò)誤...." + result);
return "password";
} else {
return "rar error";
}
}
}
} catch (Exception e) {
log.error("unRar error", e);
return e.getMessage();
} finally {
try {
inArchive.close();
randomAccessFile.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return "";
}
/*
* 解壓7z
*/
private static String un7z(String rootPath, String sourceRarPath, String destDirPath, String passWord) {
try {
File srcFile = new File(rootPath + sourceRarPath);//獲取當(dāng)前壓縮文件
// 判斷源文件是否存在
if (!srcFile.exists()) {
throw new Exception(srcFile.getPath() + "所指文件不存在");
}
//開(kāi)始解壓
SevenZFile zIn = null;
if (StringUtils.isNotBlank(passWord))
new SevenZFile(srcFile, passWord.getBytes());
else
new SevenZFile(srcFile);
SevenZArchiveEntry entry = null;
File file = null;
while ((entry = zIn.getNextEntry()) != null) {
if (!entry.isDirectory()) {
file = new File(rootPath + destDirPath, entry.getName());
if (!file.exists()) {
new File(file.getParent()).mkdirs();//創(chuàng)建此文件的上級(jí)目錄
}
OutputStream out = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(out);
int len = -1;
byte[] buf = new byte[1024];
while ((len = zIn.read(buf)) != -1) {
bos.write(buf, 0, len);
}
// 關(guān)流順序,先打開(kāi)的后關(guān)閉
bos.close();
out.close();
}
}
} catch (Exception e) {
log.error("un7z is error", e);
return e.getMessage();
}
return "";
}
public static void unFile(String rootPath, String sourcePath, String destDirPath, String passWord) {
String result = "";
if (sourcePath.toLowerCase().endsWith(".zip")) {
//Wrong password!
result = unZip(rootPath, sourcePath, destDirPath, passWord);
} else if (sourcePath.toLowerCase().endsWith(".rar")) {
//java.security.InvalidAlgorithmParameterException: password should be specified
result = unRar(rootPath, sourcePath, destDirPath, passWord);
} else if (sourcePath.toLowerCase().endsWith(".7z")) {
//PasswordRequiredException: Cannot read encrypted content from G:\ziptest\11111111.7z without a password
result = un7z(rootPath, sourcePath, destDirPath, passWord);
}
resultMap.put("resultMsg", 1);
if (StringUtils.isNotBlank(result)) {
if (result.contains("password")) resultMap.put("resultMsg", 2);
if (!result.contains("password")) resultMap.put("resultMsg", 3);
}
resultMap.put("files", data);
// System.out.println(result + "==============");
return resultMap;
}
public static void main(String[] args) {
getFileList("G:\\ziptest\\", "測(cè)試.zip", "test3333", "密碼");
}
}以上就是Java對(duì)zip,rar,7z文件帶密碼解壓實(shí)例詳解的詳細(xì)內(nèi)容,更多關(guān)于Java文件帶密碼解壓的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java操作Elasticsearch?rest-high-level-client?的基本使用
這篇文章主要介紹了Java操作Elasticsearch?rest-high-level-client?的基本使用,本篇主要講解一下?rest-high-level-client?去操作?Elasticsearch的方法,結(jié)合實(shí)例代碼給大家詳細(xì)講解,需要的朋友可以參考下2022-10-10
簡(jiǎn)單的用java實(shí)現(xiàn)讀/寫(xiě)文本文件的示例
同時(shí)也展示了如果從輸入流中讀出來(lái)內(nèi)容寫(xiě)入輸出流中(僅限文本流) 三個(gè)例子可以獨(dú)立存在,所以根據(jù)需要只看其中一個(gè)就行了。2008-07-07
Java實(shí)現(xiàn)學(xué)生管理系統(tǒng)詳解
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)學(xué)生管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2021-10-10
Java swing實(shí)現(xiàn)支持錄音等功能的鋼琴程序
這篇文章主要為大家詳細(xì)介紹了Java swing實(shí)現(xiàn)鋼琴程序,支持錄音等功能的Java鋼琴源碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
Springboot詳解RocketMQ實(shí)現(xiàn)廣播消息流程
RocketMQ作為一款純java、分布式、隊(duì)列模型的開(kāi)源消息中間件,支持事務(wù)消息、順序消息、批量消息、定時(shí)消息、消息回溯等,本篇我們了解如何實(shí)現(xiàn)廣播消息2022-06-06
Java Integer.valueOf()和Integer.parseInt()的區(qū)別說(shuō)明
這篇文章主要介紹了Java Integer.valueOf()和Integer.parseInt()的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08

