前言:zip解压Windows默认是GBK,Mac默认是UTF-8,为了保证都可以解压,就需要根据不同的文件设置不同的编码格式,本文解决方案是根据是否乱码来判断(详见下文)
如果解压过程中不需要操作文件请看方法一(三行解压到本地)
如果解压过程中需要操作文件如网盘中实现在线解压,基本实现设想就是边解压,边创建文件夹(或上传文件)到网盘数据库,看方法二
注:两种方法均引用于其他博客,但由于找不到原文地址了,望有知道的兄弟留言告知,及时加注上
方法一:
maven配置:
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>1.3.2</version>
</dependency>
代码:
package com.gxs.test.util;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.model.FileHeader;
import java.util.List;
/**
* 已解决乱码问题
*/
public class UnZipFiles {
public static void unZip(String zipPath, String destDir) throws Exception {
ZipFile zipFile = new ZipFile(zipPath);
zipFile.setFileNameCharset(getEncoding(zipPath));
zipFile.extractAll(destDir);
}
@SuppressWarnings("unchecked")
private static String getEncoding(String path) throws Exception {
String encoding = "GBK";
ZipFile zipFile = new ZipFile(path);
zipFile.setFileNameCharset(encoding);
List<FileHeader> list = zipFile.getFileHeaders();
for (int i = 0; i < list.size(); i++) {
FileHeader fileHeader = list.get(i);
String fileName = fileHeader.getFileName();
if (isMessyCode(fileName)) {
encoding = "UTF-8";
break;
}
}
return encoding;
}
private static boolean isMessyCode(String str) {
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
// 当从Unicode编码向某个字符集转换时,如果在该字符集中没有对应的编码,则得到0x3f(即问号字符?)
// 从其他字符集向Unicode编码转换时,如果这个二进制数在该字符集中没有标识任何的字符,则得到的结果是0xfffd
if ((int) c == 0xfffd) {
// 存在乱码
return true;
}
}
return false;
}
public static void main(String[] args){
/**
* 解压文件
*/
String zipFile = "E:\\ziptest\\测试1级目录.zip";
String path = "E:\\ziptest";
try {
unZip(zipFile, path);
} catch (Exception e) {
e.printStackTrace();
}
;
}
}
方法二:
代码:
package com.gxs.test.util;
import org.springframework.stereotype.Component;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.charset.Charset;
import java.util.zip.CRC32;
import java.util.zip.CheckedInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* zip压缩工具类
* @className: UnzipUtils
* @author: gxs
* @date: 2021/6/5 9:13
* @version: 1.0
*/
@Component
public class UnzipUtil {
private static final int BUFFER = 1024;
private static final String CODING_UTF8 = "UTF-8";
private static final String CODING_GBK = "GBK";
/**
* 解压入口方法
*
* @param zipPath zip文件物理地址
* @param unzipPath 解压后存放路径
* @throws Exception
*/
public static void decompress(String zipPath, String unzipPath) throws Exception {
//解压缩执行方法
decompressFile(new File(zipPath), new File(unzipPath));
}
/**
* 解压缩执行方法
*
* @param srcFile 压缩文件File实体
* @param destFile 解压路径File实体
* @throws Exception
*/
public static void decompressFile(File srcFile, File destFile) throws Exception {
//创建数据输入流
CheckedInputStream cis = new CheckedInputStream(new FileInputStream(srcFile), new CRC32());
//创建压缩输入流
ZipInputStream zis = new ZipInputStream(cis, Charset.forName(CODING_UTF8));
//异常捕获的方式判断编码格式
try {
//判断代码,如果此代码未抛出异常,则表示编码为UTF-8
zis.getNextEntry().getName();
} catch (Exception e) {
//如果乱码会抛异常,抛异常重新创建输入流,重新设置编码格式
cis = new CheckedInputStream(new FileInputStream(srcFile), new CRC32());
zis = new ZipInputStream(cis, Charset.forName(CODING_GBK));
}
//解压zip
decompressZis(destFile, zis);
//关闭流
zis.close();
}
/**
* 文件 解压缩执行方法
*
* @param destFile 目标文件
* @param zis ZipInputStream
* @throws Exception
*/
private static void decompressZis(File destFile, ZipInputStream zis) throws Exception {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
//获取当前的ZIP条目路径
String dir = destFile.getPath() + File.separator + entry.getName();
File dirFile = new File(dir);
//递归检查文件路径,路径上没有文件夹则创建,保证整条路径在本地存在
fileProber(dirFile);
//判断是否是文件夹
if (entry.isDirectory()) {
//如果是,创建文件夹
dirFile.mkdirs();
System.out.println(dirFile.getName());
} else {
//如果不是文件夹,数据流输出,生成文件
decompressFile(dirFile, zis);
}
//关闭当前的ZIP条目并定位流
zis.closeEntry();
}
}
/**
* 文件探针,当父目录不存在时,创建目录
*
* @param dirFile ZIP条目路径
*/
private static void fileProber(File dirFile) {
//获取此路径的父目录
File parentFile = dirFile.getParentFile();
//判断是否存在
if (!parentFile.exists()) {
// 递归寻找上级目录
fileProber(parentFile);
//直至存在,递归执行创建文件夹
parentFile.mkdir();
}
}
/**
* 生成文件
*
* @param destFile 目标文件
* @param zis ZipInputStream
* @throws Exception
*/
private static void decompressFile(File destFile, ZipInputStream zis) throws Exception {
//创建输出流
BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream(destFile));
//转成byte数组
int count;
byte[] data = new byte[BUFFER];
//读取并写入文件
while ((count = zis.read(data, 0, BUFFER)) != -1) {
bos.write(data, 0, count);
}
//关闭数据流
bos.close();
}
public static void main(String[] args){
try {
decompress("E:\\ziptest\\测试1级目录.zip", "E:\\ziptest\\");
} catch (Exception e) {
e.printStackTrace();
}
}
}