1、下载安装7-Zip
2、代码实现
2、1maven依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/com.github.junrar/junrar -->
<dependency>
<groupId>com.github.junrar</groupId>
<artifactId>junrar</artifactId>
<version>0.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
2、2代码实现
package com.jxx.demo001;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import com.github.junrar.Archive;
import com.github.junrar.rarfile.FileHeader;
public class ZipUtil {
/**
* 解压zip
*
* @param zipFile
* @param descDir
* @throws Exception
*/
public void unZipFiles(File zipFile, String descDir) throws Exception {
System.out.println("******************解压开始********************");
File pathFile = new File(descDir);
if (!pathFile.exists()) {
pathFile.mkdirs();
}
ZipFile zip = new ZipFile(zipFile, Charset.forName("GBK"));
for (Enumeration entries = zip.entries(); entries.hasMoreElements();) {
ZipEntry entry = (ZipEntry) entries.nextElement();
String zipEntryName = entry.getName();
InputStream in = zip.getInputStream(entry);
String outPath = (descDir + "/" + zipEntryName).replaceAll("\\*", "/");
// 判断路径是否存在,不存在则创建文件路径
File file = new File(outPath.substring(0, outPath.lastIndexOf('/')));
if (!file.exists()) {
file.mkdirs();
}
// 判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压
if (new File(outPath).isDirectory()) {
continue;
}
OutputStream out = new FileOutputStream(outPath);
byte[] buf1 = new byte[1024];
int len;
while ((len = in.read(buf1)) > 0) {
out.write(buf1, 0, len);
}
if ((zipEntryName.trim().lastIndexOf("/")) == -1) {
}
in.close();
out.close();
}
System.out.println("******************解压完毕********************");
}
/**
* 解压rar格式压缩包。
* 依赖java-unrar-0.7.jar 和 commons-logging-1.1.1.jar
*/
public void unRarFiles(File rarFile, String descDir) throws Exception {
Archive a = null;
FileOutputStream fos = null;
try {
a = new Archive(rarFile);
FileHeader fh = a.nextFileHeader();
while (fh != null) {
if (!fh.isDirectory()) {
// 1 根据不同的操作系统拿到相应的 destDirName 和 destFileName
// String compressFileName = fh.getFileNameString().trim();
String compressFileName = fh.getFileNameW().trim();
if (!existZH(compressFileName)) {
compressFileName = fh.getFileNameString().trim();
}
String destFileName = "";
String destDirName = "";
// 非windows系统
if (File.separator.equals("/")) {
destFileName = descDir + compressFileName.replaceAll("\\\\", "/");
destDirName = destFileName.substring(0, destFileName.lastIndexOf("/"));
// windows系统
} else {
destFileName = descDir + compressFileName.replaceAll("/", "\\\\");
destDirName = destFileName.substring(0, destFileName.lastIndexOf("\\"));
}
// 2创建文件夹
File dir = new File(destDirName);
if (!dir.exists() || !dir.isDirectory()) {
dir.mkdirs();
}
// 3解压缩文件
fos = new FileOutputStream(new File(destFileName));
a.extractFile(fh, fos);
fos.close();
fos = null;
}
fh = a.nextFileHeader();
}
a.close();
a = null;
} catch (Exception e) {
throw e;
} finally {
if (fos != null) {
try {
fos.close();
fos = null;
} catch (Exception e) {
e.printStackTrace();
}
}
if (a != null) {
try {
a.close();
a = null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static boolean existZH(String str) {
String regEx = "[\\u4e00-\\u9fa5]";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(str);
while (m.find()) {
return true;
}
return false;
}
/**
* 文件夹遍历
*
* @param path
* @throws Exception
*/
public void traverse(String path, String parent_id) throws Exception {
System.out.println("path---->" + path);
File file = new File(path);
Map<String, Object> map = new HashMap<String, Object>();
if (file.exists()) {
File[] files = file.listFiles();
if (files.length == 0) {
System.out.println("文件夹是空的!");
return;
} else {
String k_id = UUID.randomUUID().toString();
for (File file2 : files) {
if (file2.isDirectory()) {// 文件夹
traverse(file2.getAbsolutePath(), parent_id);
parent_id = k_id;
} else if (file2.isFile()) {// 文件
}
}
}
} else {
System.out.println("文件不存在!");
}
}
/**
* 采用命令行方式解压文件
*
* @param zipFile 压缩文件
* @param destDir 解压结果路径
* @param cmdPath 7z.exe的路径
* @return
* 存在proc.waitFor()阻塞问题--》解决看cmd7zUnzipUpdate方法
*/
public static void cmd7zUnzip(File rarFile, String destDir) {
// 解决路径中存在/..格式的路径问题
destDir = new File(destDir).getAbsoluteFile().getAbsolutePath();
while (destDir.contains("..")) {
String[] sepList = destDir.split("\\\\");
destDir = "";
for (int i = 0; i < sepList.length; i++) {
if (!"..".equals(sepList[i]) && i < sepList.length - 1 && "..".equals(sepList[i + 1])) {
i++;
} else {
destDir += sepList[i] + File.separator;
}
}
}
String path = System.getProperty("user.dir");
boolean bool = false;
if (rarFile.exists()) {
// 开始调用命令行解压,参数-o+是表示覆盖的意思
String cmdPath = "E:/jiangxx/zip7z/7-Zip/7z.exe";
// 所有空格都替换成带有双引号的空格
cmdPath = cmdPath.replaceAll(" ", "\" \"");
String cmd = cmdPath + " x " + rarFile.getPath() + " -o" + destDir;
System.out.println(cmd);
try {
Process proc = Runtime.getRuntime().exec(cmd);
if (proc.waitFor() != 0) {
if (proc.exitValue() == 0) {
bool = false;
}
} else {
bool = true;
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("解压" + (bool ? "成功" : "失败"));
}
}
/**
* 采用命令行方式解压文件
*
* @param zipFile 压缩文件
* @param destDir 解压结果路径
* @param cmdPath 7z.exe的路径
* @return
* update:20200805--解决proc.waitFor()阻塞问题
*/
public static void cmd7zUnzipUpdate(File rarFile, String destDir) {
// 解决路径中存在/..格式的路径问题
destDir = new File(destDir).getAbsoluteFile().getAbsolutePath();
while (destDir.contains("..")) {
String[] sepList = destDir.split("\\\\");
destDir = "";
for (int i = 0; i < sepList.length; i++) {
if (!"..".equals(sepList[i]) && i < sepList.length - 1 && "..".equals(sepList[i + 1])) {
i++;
} else {
destDir += sepList[i] + File.separator;
}
}
}
String path = System.getProperty("user.dir");
boolean bool = false;
if (rarFile.exists()) {
// 开始调用命令行解压,参数-o+是表示覆盖的意思
String cmdPath = "E:/jiangxx/zip7z/7-Zip/7z.exe";
// 所有空格都替换成带有双引号的空格
cmdPath = cmdPath.replaceAll(" ", "\" \"");
String cmd = cmdPath + " x " + rarFile.getPath() + " -o" + destDir;
System.out.println(cmd);
//"-o" +destDir =>注意"-o"不能加空格
String[] cmdArr = {cmdPath,"x",rarFile.getPath(),"-o" +destDir};
try {
//Process proc = Runtime.getRuntime().exec(cmd);
//注意:
//1、proc.waitFor()可能会造成阻塞,故用new ProcessBuilder(cmd).redirectErrorStream(true).start();
//2、new ProcessBuilder(cmdArr),命令不能包含空格,传入数组
Process proc = new ProcessBuilder(cmdArr).redirectErrorStream(true).start();
try {
if (proc.waitFor() != 0) {
if (proc.exitValue() == 0) {
bool = false;
}
} else {
bool = true;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
proc.getErrorStream().close();
proc.getInputStream().close();
proc.getOutputStream().close();
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("解压" + (bool ? "成功" : "失败"));
}
}
//测试
public static void main(String[] args) {
cmd7zUnzip(new File("E:/testwinrar/测试.zip"), "E:/testwinrar/666");
}
}
补充说明内容:
使用jdk自带的运行时变量 RunTime.getRunTime() 去执行bash命令。因为该bash操作耗时比较长,所以使用了Process.waitFor()去等待子线程运行结束。
这个时候发现程序卡在waitFor()没有继续往下执行。
官方解释:
/** * Causes the current thread to wait, if necessary, until the * process represented by this {@code Process} object has * terminated. This method returns immediately if the subprocess * has already terminated. If the subprocess has not yet * terminated, the calling thread will be blocked until the * subprocess exits. * * @return the exit value of the subprocess represented by this * {@code Process} object. By convention, the value * {@code 0} indicates normal termination. * @throws InterruptedException if the current thread is * {@linkplain Thread#interrupt() interrupted} by another * thread while it is waiting, then the wait is ended and * an {@link InterruptedException} is thrown. */ abstract public int waitFor() throws InterruptedException;
waitFor:等待子进程执行结束,或者已终止子进程,此方法立即返回。
当RunTime对象调用exec方法后,jvm会创建一个子进程,该子进程与jvm建立三个管道连接:标准输入流、标准输出流、标准错误流。假设该子进程不断向标准输入流、标准输出流写数据,而jvm不读取的话,会导致缓冲区塞满而无法继续写数据,最终堵塞在waitFor这里。java.lang.ProcessBuilder.redirectErrorStream() 方法告诉此进程生成器是否合并标准错误和标准输出。如果此属性为true,则通过子进程所产生的任何错误输出随后由该对象的start()方法启动将与标准输出合并,这样既可以用Process.getInputStream()方法来读取。此使得更容易与对应的输出相关的错误消息。初始值是false。