Content Table

Java 解压 zip 文件

使用 Apache commons-compress 解压 zip 文件是件很幸福的事,可以解决 zip 包中文件名有中文时跨平台的乱码问题,不管文件是在 Windows 压缩的还是在 Mac,Linux 压缩的,解压后都没有再出现乱码问题了。

例如 Windows 下压缩 河堤.txt河堤.zip,然后传给 Mac 用户,Mac 用户解压后会发现得到的文件名是乱码,因为 Windows 压缩的时候使用的是系统的编码 GB2312,而 Mac 系统默认的编码是 UTF-8,于是出现了乱码。

Gradle 依赖

1
2
3
4
5
dependencies {
compile 'org.apache.commons:commons-compress:1.11'
compile 'org.apache.commons:commons-lang3:3.4'
compile 'commons-io:commons-io:2.5'
}

解压程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class ExtractZip {
public static final int BUFFER_SIZE = 1024;

/**
* 解压 zip 文件
* @param zipFile zip 压缩文件
* @param destDir zip 压缩文件解压后保存的目录
* @param encoding zip 文件的编码
* @return 返回 zip 压缩文件里的文件名的 list
* @throws Exception
*/
public static List<String> unZip(File zipFile, String destDir, String encoding) throws Exception {
// 如果 destDir 为 null, 空字符串, 或者全是空格, 则解压到压缩文件所在目录
if(StringUtils.isBlank(destDir)) {
destDir = zipFile.getParent();
}

destDir = destDir.endsWith(File.separator) ? destDir : destDir + File.separator;
ZipArchiveInputStream is = null;
List<String> fileNames = new ArrayList<String>();

try {
is = new ZipArchiveInputStream(new BufferedInputStream(new FileInputStream(zipFile), BUFFER_SIZE), encoding);
ZipArchiveEntry entry = null;

while ((entry = is.getNextZipEntry()) != null) {
fileNames.add(entry.getName());
File file = new File(destDir, entry.getName());

if (entry.isDirectory()) {
FileUtils.forceMkdir(file); // 创建文件夹,如果中间有路径会自动创建
} else {
OutputStream os = null;

try {
FileUtils.touch(file);
os = new FileOutputStream(new File(destDir, entry.getName()));
IOUtils.copy(is, os);
} finally {
IOUtils.closeQuietly(os);
}
}
}
} catch(Exception e) {
e.printStackTrace();
throw e;
} finally {
IOUtils.closeQuietly(is);
}

return fileNames;
}

/**
* 解压 zip 文件
* @param zipFile zip 压缩文件的路径
* @param destDir zip 压缩文件解压后保存的目录
* @param encoding zip 文件的编码
* @return 返回 zip 压缩文件里的文件名的 list
* @throws Exception
*/
public static List<String> unZip(String zipFile, String destDir, String encoding) throws Exception {
File zipfile = new File(zipFile);
return unZip(zipfile, destDir, encoding);
}

public static List<String> unZip(String zipFile, String destDir) throws Exception {
return unZip(zipFile, destDir, "UTF-8");
}

public static void main(String[] args) throws Exception {
List<String> names = unZip("/Users/Biao/Desktop/x.zip", "/Users/Biao/Desktop/x");
System.out.println(names);
}
}

测试

例如我这测试用的压缩文件是在 Windows 压缩的,解压程序在 Mac 执行的,解压后没有乱码,输出也没有乱码:

[测试页面.files/, 测试页面.files/image001.jpg, 测试页面.htm]