JDK 原生 java.util.zip 在處理中文文件名時易產生亂碼。本文推薦使用 Apache Commons Compress(或 Ant 的 org.apache.tools.zip)實現 ZIP 壓縮,完美支援中文路徑,並提供目錄遞歸壓縮完整示例。
<!-- Maven -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.26.0</version> <!-- 請用最新版 -->
</dependency>
或直接使用 Ant 包:org.apache.tools.zip.ZipOutputStream。
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import java.io.*;
import java.nio.charset.StandardCharsets;
public class ZipUtils {
private static final int BUFFER_SIZE = 8192;
/**
* 將指定目錄壓縮為 ZIP 文件
* @param sourceDirPath 待壓縮目錄絕對路徑
* @param zipFilePath 生成的 ZIP 文件路徑
* @throws IOException IO 異常
*/
public static void zipDirectory(String sourceDirPath, String zipFilePath) throws IOException {
File sourceDir = new File(sourceDirPath);
if (!sourceDir.isDirectory()) {
throw new IllegalArgumentException("源路徑非目錄: " + sourceDirPath);
}
try (FileOutputStream fos = new FileOutputStream(zipFilePath);
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(fos))) {
// 關鍵:設置編碼為 UTF-8,解決中文亂碼
zos.setEncoding(StandardCharsets.UTF_8.name());
zipDirectoryRecursive(sourceDir, sourceDir.getName(), zos);
zos.finish();
}
}
private static void zipDirectoryRecursive(File dir, String basePath, ZipOutputStream zos) throws IOException {
File[] files = dir.listFiles();
if (files == null) return; // 權限不足等
for (File file : files) {
String entryName = basePath + "/" + file.getName();
if (file.isDirectory()) {
// 目錄條目以 / 結尾
zos.putNextEntry(new ZipEntry(entryName + "/"));
zos.closeEntry();
zipDirectoryRecursive(file, entryName, zos);
} else {
try (FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis)) {
zos.putNextEntry(new ZipEntry(entryName));
byte[] buffer = new byte[BUFFER_SIZE];
int len;
while ((len = bis.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
zos.closeEntry();
}
}
}
}
}
zos.setEncoding("UTF-8") 是解決中文亂碼的核心,JDK 原生 ZipOutputStream 不支援此方法。/ 結尾的 Entry,否則解壓時可能不創建空目錄。BufferedInputStream 提升讀取性能,緩衝區 8KB 適中。public static void main(String[] args) {
try {
ZipUtils.zipDirectory("/data/docs", "/output/docs.zip");
System.out.println("壓縮完成");
} catch (IOException e) {
e.printStackTrace();
}
}
setEncoding("UTF-8"),且解壓工具也支援 UTF-8(現代解壓軟體均支援)。