How to decompress zip, rar, and 7z files with password in Java?
前言
在一些日常业务中,会遇到一些琐碎文件需要统一打包到一个压缩包中上传,业务方在后台接收到压缩包后自行解压,然后解析相应文件。而且可能涉及安全保密,因此会在压缩时带上密码,要求后台业务可以指定密码进行解压。
应用环境说明:jdk1.8,maven3.x,需要基于java语言实现对zip、rar、7z等常见压缩包的解压工作。
首先关于zip和rar、7z等压缩工具和压缩算法就不在此赘述,下面通过一个数据对比,使用上述三种不同的压缩算法,采用默认的压缩方式,看到压缩的文件大小如下:
转换成图表看得更直观,如下图:
从以上图表可以看到,7z的压缩率是最高,而zip压缩率比较低,rar比zip稍微好点。单纯从压缩率看,7z>rar4>rar5>zip。
实现代码
下面具体说明在java中如何进行相应解压:
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 { // 第一个参数是需要解压的压缩包路径,第二个参数参考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成功:密码错误或者其他错误...." + 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);//获取当前压缩文件 // 判断源文件是否存在 if (!srcFile.exists()) { throw new Exception(srcFile.getPath() + "所指文件不存在"); } //开始解压 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();//创建此文件的上级目录 } 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); } // 关流顺序,先打开的后关闭 bos.close(); out.close(); } } } catch (Exception e) { log.error("un7z is error", e); return e.getMessage(); } return ""; }
5、解压统一入口封装
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、测试代码
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解压耗时==" + (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解压耗时==" + (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解压耗时==" + (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解压耗时==" + (zend - zstart)+ "毫秒"); System.out.println("============================================================");
在控制台中可以看到以下结果:
总结:本文采用java语言实现了对zip和rar、7z文件的解压统一算法。并对比了相应的解压速度,支持传入密码进行在线解压。
本文参考代码在补充内容里,不过代码直接运行有问题,这里进行了调整,主要优化的点如下:
1、pom.xml 遗漏了slf4j、commons-lang3、xdocreport等依赖
2、zip路径优化
3、去掉一些无用信息
4、优化异常信息
补充
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.实现代码如下
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 { // 第一个参数是需要解压的压缩包路径,第二个参数参考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成功:密码错误或者其他错误...." + 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);//获取当前压缩文件 // 判断源文件是否存在 if (!srcFile.exists()) { throw new Exception(srcFile.getPath() + "所指文件不存在"); } //开始解压 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();//创建此文件的上级目录 } 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); } // 关流顺序,先打开的后关闭 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\\", "测试.zip", "test3333", "密码"); } }
The above is the detailed content of How to decompress zip, rar, and 7z files with password in Java?. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











Java 8 introduces the Stream API, providing a powerful and expressive way to process data collections. However, a common question when using Stream is: How to break or return from a forEach operation? Traditional loops allow for early interruption or return, but Stream's forEach method does not directly support this method. This article will explain the reasons and explore alternative methods for implementing premature termination in Stream processing systems. Further reading: Java Stream API improvements Understand Stream forEach The forEach method is a terminal operation that performs one operation on each element in the Stream. Its design intention is

PHP is a scripting language widely used on the server side, especially suitable for web development. 1.PHP can embed HTML, process HTTP requests and responses, and supports a variety of databases. 2.PHP is used to generate dynamic web content, process form data, access databases, etc., with strong community support and open source resources. 3. PHP is an interpreted language, and the execution process includes lexical analysis, grammatical analysis, compilation and execution. 4.PHP can be combined with MySQL for advanced applications such as user registration systems. 5. When debugging PHP, you can use functions such as error_reporting() and var_dump(). 6. Optimize PHP code to use caching mechanisms, optimize database queries and use built-in functions. 7

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHP is suitable for web development, with simple syntax and high execution efficiency. 2. Python is suitable for data science and machine learning, with concise syntax and rich libraries.

PHP is suitable for web development, especially in rapid development and processing dynamic content, but is not good at data science and enterprise-level applications. Compared with Python, PHP has more advantages in web development, but is not as good as Python in the field of data science; compared with Java, PHP performs worse in enterprise-level applications, but is more flexible in web development; compared with JavaScript, PHP is more concise in back-end development, but is not as good as JavaScript in front-end development.

PHP and Python each have their own advantages and are suitable for different scenarios. 1.PHP is suitable for web development and provides built-in web servers and rich function libraries. 2. Python is suitable for data science and machine learning, with concise syntax and a powerful standard library. When choosing, it should be decided based on project requirements.

Capsules are three-dimensional geometric figures, composed of a cylinder and a hemisphere at both ends. The volume of the capsule can be calculated by adding the volume of the cylinder and the volume of the hemisphere at both ends. This tutorial will discuss how to calculate the volume of a given capsule in Java using different methods. Capsule volume formula The formula for capsule volume is as follows: Capsule volume = Cylindrical volume Volume Two hemisphere volume in, r: The radius of the hemisphere. h: The height of the cylinder (excluding the hemisphere). Example 1 enter Radius = 5 units Height = 10 units Output Volume = 1570.8 cubic units explain Calculate volume using formula: Volume = π × r2 × h (4

PHPhassignificantlyimpactedwebdevelopmentandextendsbeyondit.1)ItpowersmajorplatformslikeWordPressandexcelsindatabaseinteractions.2)PHP'sadaptabilityallowsittoscaleforlargeapplicationsusingframeworkslikeLaravel.3)Beyondweb,PHPisusedincommand-linescrip

The reasons why PHP is the preferred technology stack for many websites include its ease of use, strong community support, and widespread use. 1) Easy to learn and use, suitable for beginners. 2) Have a huge developer community and rich resources. 3) Widely used in WordPress, Drupal and other platforms. 4) Integrate tightly with web servers to simplify development deployment.
