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

基於 Apache Ant 實現 ZIP 壓縮解壓工具類:跨平台中文路徑完美支持

     編輯:Java 相關知識

為什麼選擇 Apache Ant?

JDK 自帶 java.util.zip 在處理中文路徑編碼時存在已知缺陷(早期版本僅支持 UTF-8,且行為不一致)。Apache Ant 的 org.apache.tools.zip 包和 Expand 任務提供:

  • 顯式指定編碼(setEncoding("UTF-8"))
  • 成熟穩定,Ant 自身構建系統長期驗證
  • 一行代碼完成解壓,避免手寫遞歸遍歷的 Bug

Maven 依賴

<dependency>
    <groupId>org.apache.ant</groupId>
    <artifactId>ant</artifactId>
    <version>1.10.14</version> <!-- 或更新版本 -->
</dependency>

工具類完整實現

import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Expand;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import java.io.*;

public class ZipUtil {
    private static final String ENCODING = "UTF-8";

    /** 壓縮文件/目錄 */
    public static void zip(String inputPath, String zipPath) {
        File inputFile = new File(inputPath);
        if (!inputFile.exists()) throw new RuntimeException("源文件不存在: " + inputPath);

        File zipFile = new File(zipPath);
        if (!zipFile.getParentFile().exists() && !zipFile.getParentFile().mkdirs())
            throw new RuntimeException("無法創建目標目錄: " + zipFile.getParent());

        try (FileOutputStream fos = new FileOutputStream(zipFile);
             BufferedOutputStream bos = new BufferedOutputStream(fos);
             ZipOutputStream zos = new ZipOutputStream(bos, ENCODING)) {  // Ant ZipOutputStream 支持編碼構造參數

            zip(zos, inputFile, inputFile.getName());
            zos.finish(); // 關鍵:寫入中央目錄
        } catch (IOException e) {
            throw new RuntimeException("壓縮失敗", e);
        }
    }

    private static void zip(ZipOutputStream zos, File file, String base) throws IOException {
        if (file.isDirectory()) {
            File[] children = file.listFiles();
            if (children != null) {
                for (File child : children) {
                    zip(zos, child, base + "/" + child.getName());
                }
            }
        } else {
            zos.putNextEntry(new ZipEntry(base));
            try (FileInputStream fis = new FileInputStream(file);
                 BufferedInputStream bis = new BufferedInputStream(fis)) {
                byte[] buffer = new byte[8192];
                int len;
                while ((len = bis.read(buffer)) != -1) {
                    zos.write(buffer, 0, len);
                }
            }
            zos.closeEntry();
        }
    }

    /** 解壓 ZIP 到指定目錄 */
    public static void unzip(String zipPath, String destDir) {
        File zipFile = new File(zipPath);
        if (!zipFile.exists()) throw new RuntimeException("ZIP 文件不存在: " + zipPath);

        File dest = new File(destDir);
        if (!dest.exists() && !dest.mkdirs()) throw new RuntimeException("無法創建解壓目錄: " + destDir);

        Project proj = new Project();
        Expand expand = new Expand();
        expand.setProject(proj);
        expand.setSrc(zipFile);
        expand.setDest(dest);
        expand.setEncoding(ENCODING);
        expand.setOverwrite(true); // 覆蓋已存在文件
        expand.execute(); // 核心一行
    }
}

關鍵點詳解

  1. 壓縮編碼:new ZipOutputStream(bos, ENCODING) 顯式指定 UTF-8,解決中文文件名亂碼。
  2. finish() vs close():finish() 僅寫入中央目錄結束標記,不關閉底層流;配合 try-with-resources 由外層流關閉。
  3. 解壓 Overwrite:setOverwrite(true) 避免文件存在報錯。
  4. Ant Project 初始化:new Project() 必須設置給 Expand,否則 NPE。

單元測試示例

public class ZipUtilTest {
    @Test
    public void testZipAndUnzip() throws IOException {
        File tempDir = Files.createTempDirectory("ziptest").toFile();
        File srcFile = new File(tempDir, "source.txt");
        Files.writeString(srcFile.toPath(), "中文測試內容");

        String zipPath = new File(tempDir, "archive.zip").getAbsolutePath();
        String destDir = new File(tempDir, "out").getAbsolutePath();

        ZipUtil.zip(srcFile.getAbsolutePath(), zipPath);
        ZipUtil.unzip(zipPath, destDir);

        File outFile = new File(destDir, "source.txt");
        assertTrue(outFile.exists());
        assertEquals("中文測試內容", Files.readString(outFile.toPath()));
    }
}

替代方案對比

方案中文支持API 簡潔度依賴大小推薦場景
JDK java.util.zip需 JDK 7+ 顯式編碼,歷史版本有坑較繁瑣零依賴簡單項目、不可引入第三方
Apache Ant (本文)原生支持,穩定解壓極簡,壓縮需遞歸~1.5MB企業級項目、需可靠中文支持
Apache Commons Compress完美支持豐富、標準~500KB現代項目、支持多種格式(tar/gzip/7z)
ZeroTurnaround zipt完美最簡單~100KB輕量級、只需壓縮解壓
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved