首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 使用 Apache Commons Compress 創建 ZIP 壓縮文件(解決中文亂碼)

     編輯:Java 相關知識

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 適中。
  • 資源管理:採用 try-with-resources 確保流關閉,避免句柄洩漏。

使用示例

public static void main(String[] args) {
    try {
        ZipUtils.zipDirectory("/data/docs", "/output/docs.zip");
        System.out.println("壓縮完成");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

常見問題

  1. 壓縮後文件名亂碼:確認調用了 setEncoding("UTF-8"),且解壓工具也支援 UTF-8(現代解壓軟體均支援)。
  2. 大文件內存溢出:採用流式寫入,不將整文件讀入內存,無此風險。
  3. 空目錄不保留:代碼中已處理目錄 Entry,空目錄會被保留。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved