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

Java GZIP 文件壓縮解壓工具類完整實現:流式處理、多重載、異常安全

     編輯:Java 相關知識

前言

GZIP 是廣泛使用的無損壓縮格式。本文提供生產級 GZipUtils 工具類,支援 byte[]、File、InputStream/OutputStream、String 路徑四種輸入源的壓縮與解壓,採用流式處理避免大文件內存溢出,完善異常處理與資源釋放。

核心常量與類結構

public abstract class GZipUtils {
    public static final int BUFFER = 1024;      // 1KB 緩衝區
    public static final String EXT = ".gz";     // 壓縮文件後綴

    // 壓縮入口:byte[]、File、InputStream、String 路徑
    // 解壓入口:byte[]、File、InputStream、String 路徑
    // 所有方法最終委託給核心流式處理方法
}

核心流式壓縮邏輯

使用 GZIPOutputStream 包裝輸出流,分塊讀取輸入流寫入,最後調用 finish() 確保壓縮數據刷新。

public static void compress(InputStream is, OutputStream os) throws Exception {
    try (GZIPOutputStream gos = new GZIPOutputStream(os)) {
        byte[] data = new byte[BUFFER];
        int count;
        while ((count = is.read(data, 0, BUFFER)) != -1) {
            gos.write(data, 0, count);
        }
        gos.finish();  // 關鍵:寫入 GZIP 尾部標記
        gos.flush();
    }
}

核心流式解壓邏輯

使用 GZIPInputStream 包裝輸入流,透明解壓讀取,寫入輸出流。

public static void decompress(InputStream is, OutputStream os) throws Exception {
    try (GZIPInputStream gis = new GZIPInputStream(is)) {
        byte[] data = new byte[BUFFER];
        int count;
        while ((count = gis.read(data, 0, BUFFER)) != -1) {
            os.write(data, 0, count);
        }
    }
}

多重載方法體系

場景壓縮方法解壓方法特點
內存數據compress(byte[]) → byte[]decompress(byte[]) → byte[]ByteArrayInputStream/OutputStream 內存流
文件對象compress(File, boolean delete)decompress(File, boolean delete)自動生成 .gz 後綴、可選刪除源文件
流處理compress(InputStream, OutputStream)decompress(InputStream, OutputStream)核心邏輯、最大靈活性、管道流適用
文件路徑compress(String, boolean delete)decompress(String, boolean delete)路徑字符串便捷入口、內部轉 File

文件壓縮完整示例

public static void compress(File file, boolean delete) throws Exception {
    try (FileInputStream fis = new FileInputStream(file);
         FileOutputStream fos = new FileOutputStream(file.getPath() + EXT)) {
        compress(fis, fos);  // 委託核心流式方法
    }
    if (delete) file.delete();
}

文件解壓完整示例

public static void decompress(File file, boolean delete) throws Exception {
    String targetPath = file.getPath().replace(EXT, "");
    try (FileInputStream fis = new FileInputStream(file);
         FileOutputStream fos = new FileOutputStream(targetPath)) {
        decompress(fis, fos);
    }
    if (delete) file.delete();
}

關鍵技術點與最佳實踐

  • try-with-resources:JDK 7+ 語法自動關閉流,即使異常也保證資源釋放 (注意:GZIPOutputStream 需手動 finish() 後再 close)
  • finish() vs close():GZIPOutputStream 必須先 finish() 寫入 CRC32、ISIZE 等尾部信息,close() 會自動調用 finish() 但顯式調用更清晰
  • 緩衝區大小:1024/4096/8192 字節均可,大文件建議 8KB-64KB 平衡內存與系統調用次數
  • 大文件支援:流式處理無文件大小限制,單次內存佔用 = 緩衝區大小
  • 並發安全:所有方法無共享狀態,線程安全,可並發調用
  • 編碼無關:位元組級操作,不涉及字符編碼,適用於二進制/文本混合

生產環境增強建議

  1. 校驗和驗證:壓縮後計算 CRC32/MD5,解壓後比對確保數據完整性
  2. 進度回調:添加 ProgressListener 參數,實時回調已處理字節數/百分比
  3. 多線程並行:大文件分塊並行壓縮 (需自定義分塊格式),或多文件並發處理
  4. 壓縮級別控制:使用 Deflater(DEFAULT_COMPRESSION) 構造 GZIPOutputStream 控制速度/比率權衡
  5. 臨時文件原子性:壓縮寫入 .tmp 文件,成功後 rename 替換目標,防止部分寫入污染
  6. 異常分類:區分 IOException、CorruptGZIPException、FileNotFoundException 等具體類型

常見問題排查

問題原因解決
解壓後文件損壞/大小為0未調用 gos.finish() 或流未正確關閉確保 try-with-resources 包含 finish() 或顯式調用
GZIPInputStream 讀取拋出 EOFException輸入非標準 GZIP 格式、文件截斷、未壓縮文件誤作解壓驗證文件魔數 (0x1f 0x8b)、捕獲異常友好提示
壓縮大文件 OOM誤將整文件讀入內存 (byte[])堅持流式分塊讀寫、避免 toByteArray()
中文文件名亂碼GZIP 不存儲文件名元數據應用層維護文件名映射、或使用 ZIP 格式
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved