版权声明:士,不可以不弘毅,任重而道远 https://blog.csdn.net/superbeyone/article/details/83339089
文章目录
Java解压缩zip文件工具类(支持zip文件夹下多级目录结构)
1. 前言
由于工作需要一个能够解压缩zip的工具类,但查看了不少博客,发现查看的文章里都只支持zip文件夹下的一级文件结构,但实际生活中,zip文件夹下存在多级目录及文件是很随意的事情,所以萌生了封装这样一个能够解压缩多级目录结构文件的想法。
2. 正文
2.1 解压缩后文件目录结构展示
2.2 注意事项
- 若zip文件中包含中文的话,可能需要制定字符编码,若不指定的话,默认使用
UTF8
字符编码 - Windows系统压缩编码一般为
GBK
,GB2312
,UTF8
,Linux系统压缩编码一般为UTF8
- 测试数据使用
GB2312
能够正常解码,使用其它均不能正常解码
2.3 异常
2.3.1 可能会遇到的异常
java.lang.IllegalArgumentException: MALFORMED
at java.util.zip.ZipCoder.toString(ZipCoder.java:58)
at java.util.zip.ZipFile.getZipEntry(ZipFile.java:583)
at java.util.zip.ZipFile.access$900(ZipFile.java:60)
at java.util.zip.ZipFile$ZipEntryIterator.next(ZipFile.java:539)
at java.util.zip.ZipFile$ZipEntryIterator.nextElement(ZipFile.java:514)
at java.util.zip.ZipFile$ZipEntryIterator.nextElement(ZipFile.java:495)
at com.tdt.sc.utils.FileUtils.unpack(FileUtils.java:91)
at com.tdt.sc.utils.FileUtils.unpack(FileUtils.java:54)
at com.tdt.sc.utils.FileUtils.unpack(FileUtils.java:34)
at com.tdt.sc.utils.FileUtils.main(FileUtils.java:23)
2.3.2 解决方案
- 此异常为字符编码解码异常
- 建议使用其它字符编码进行解码,具体参见 注意事项
2.4 具体代码实现
import java.io.*;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* @program:
* @description: 文件解压缩工具类
* @author: Mr.superbeyone
* @create: 2018-10-23 14:04
**/
public class FileUtils {
/**
* 此方法将默认设置解压缩后文件的保存路径为zip文件所在路径
* 即解压缩到当前文件夹下
* @param zip zip文件位置
* @param charsetName 字符编码
*/
public static void unpack(String zip, String charsetName) {
unpack(new File(zip), charsetName);
}
/**
*
* @param zip zip文件位置
* @param outputDir 解压缩后文件保存路径
* @param charsetName 字符编码
*/
public static void unpack(String zip, String outputDir, String charsetName) {
unpack(new File(zip), new File(outputDir), charsetName);
}
/**
* 此方法将默认设置解压缩后文件的保存路径为zip文件所在路径
* 即解压缩到当前文件夹
* @param zip zip文件位置
* @param charsetName 字符编码
*/
public static void unpack(File zip, String charsetName) {
unpack(zip, null, charsetName);
}
/**
*
* @param zip zip文件位置
* @param outputDir 解压缩后文件保存路径
*/
public static void unpack(File zip, File outputDir) {
unpack(zip, outputDir, "");
}
/**
*
* @param zip zip文件位置
* @param outputDir 解压缩后文件保存路径
* @param charsetName 字符编码
*/
public static void unpack(File zip, File outputDir, String charsetName) {
FileOutputStream out = null;
InputStream in = null;
//读出文件数据
ZipFile zipFileData = null;
ZipFile zipFile = null;
try {
//若目标保存文件位置不存在
if (outputDir != null) if (!outputDir.exists()) {
outputDir.mkdirs();
}
if (charsetName != null && charsetName != "") {
zipFile = new ZipFile(zip.getPath(), Charset.forName(charsetName));
} else {
zipFile = new ZipFile(zip.getPath(), Charset.forName("utf8"));
}
//zipFile = new ZipFile(zip.getPath(), Charset.forName(charsetName));
Enumeration<? extends ZipEntry> entries = zipFile.entries();
//处理创建文件夹
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
String filePath = "";
if (outputDir == null) {
filePath = zip.getParentFile().getPath() + File.separator + entry.getName();
} else {
filePath = outputDir.getPath() + File.separator + entry.getName();
}
File file = new File(filePath);
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs();
}
if (parentFile.isDirectory()) {
continue;
}
}
if (charsetName != null && charsetName != "") {
zipFileData = new ZipFile(zip.getPath(), Charset.forName(charsetName));
} else {
zipFileData = new ZipFile(zip.getPath(), Charset.forName("utf8"));
}
Enumeration<? extends ZipEntry> entriesData = zipFileData.entries();
while (entriesData.hasMoreElements()) {
ZipEntry entry = entriesData.nextElement();
in = zipFile.getInputStream(entry);
String filePath = "";
if (outputDir == null) {
filePath = zip.getParentFile().getPath() + File.separator + entry.getName();
} else {
filePath = outputDir.getPath() + File.separator + entry.getName();
}
File file = new File(filePath);
if (file.isDirectory()) {
continue;
}
out = new FileOutputStream(filePath);
int len = -1;
byte[] bytes = new byte[1024];
while ((len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
out.flush();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
in.close();
zipFile.close();
zipFileData.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.4 遗留问题
以下问题未做处理:
- 压缩文件内可能包含其它压缩文件
- 压缩文件内若存在空文件夹,则该文件夹会被当成文件处理,即生成以该文件夹名命名的空文件