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

Java API 資料壓縮與解壓縮實戰:java.util.zip 完整指南

     編輯:Java 相關知識

前言:為什麼需要資料壓縮?

資料來源常含冗餘資訊,導致儲存空間浪費與傳輸頻寬壓力。雖然增加硬體設備可緩解,但成本高昂。更有效的方案是透過演算法以更緊湊編碼表示資料。本文介紹資料壓縮原理、java.util.zip 套件用法、序列化物件壓縮、以及客戶端/伺服器應用中的效能優化實作。

一、資料壓縮核心概念

1. 執行長度編碼

最簡單的壓縮形式,針對連續重複字元。例如字串 BBBBHHDDXXXXKKKKWWZZZZ 可編碼為 4B2H2D4X4K2W4Z,其中 4B 代表 4 個 B。此法適用於重複度高的資料(如單色位圖)。

2. 位圖與向量圖儲存比較

  • 位圖: 逐像素儲存,可用 RLE 壓縮逐行編碼(如 0,40 表示 40 個白點)
  • 向量圖: 以幾何指令儲存(如 矩形 11,3,20,5),極度精簡

帶執行長度編碼資訊的位圖

圖表 1:帶執行長度編碼資訊的位圖

3. 其他壓縮技術

  • 變長編碼 / 霍夫曼編碼
  • LZW、Deflate 等演算法

詳細理論請參考資料與影像壓縮專業書籍。

4. 壓縮效益與架構

  • 減少儲存需求
  • 提升傳輸速率(相同頻寬下傳更多有效資訊)
  • 可由軟體或專用硬體實現

資料壓縮方塊圖

圖形 2:資料壓縮方塊圖

二、ZIP vs GZIP:格式差異

特性ZIP (WinZip/PKZIP)GZIP (gzip)
功能定位兼具封存與壓縮僅壓縮,不封存
Unix 慣用流程單一工具完成tar 封存 → gzip 壓縮
Java 支援java.util.zip 完整支援java.util.zip 完整支援

三、java.util.zip 套件核心類別

提供相容 ZIP/GZIP 格式的壓縮、解壓縮、校驗和計算功能。核心介面與類別如下:

類別/介面類型用途
Checksum介面Adler32、CRC32 實作基礎
Adler32 / CRC32類別計算資料流校驗和
CheckedInputStream / OutputStream類別讀寫時同步維護校驗和
Deflater / Inflater類別ZLIB 庫通用壓縮/解壓縮引擎
DeflaterOutputStream / InflaterInputStream類別串流過濾器,處理壓縮格式
GZIPInputStream / OutputStream類別GZIP 格式專用串流
ZipEntry類別代表 ZIP 檔案內單一條目
ZipFile類別隨機存取讀取 ZIP 檔條目
ZipInputStream / OutputStream類別ZIP 格式串流讀寫
DataFormatException / ZipException異常資料格式錯誤 / ZIP 專用錯誤

註:ZLIB 庫原為 PNG 格式開發,不受專利限制。

四、實作範例:壓縮與解壓縮資料流

1. GZIP 壓縮/解壓縮單一檔案

// 壓縮
try (FileInputStream fis = new FileInputStream("data.txt");
     FileOutputStream fos = new FileOutputStream("data.gz");
     GZIPOutputStream gzos = new GZIPOutputStream(fos)) {
    byte[] buffer = new byte[1024];
    int len;
    while ((len = fis.read(buffer)) > 0) {
        gzos.write(buffer, 0, len);
    }
}

// 解壓縮
try (GZIPInputStream gzis = new GZIPInputStream(new FileInputStream("data.gz"));
     FileOutputStream fos = new FileOutputStream("data.txt")) {
    byte[] buffer = new byte[1024];
    int len;
    while ((len = gzis.read(buffer)) > 0) {
        fos.write(buffer, 0, len);
    }
}

2. ZIP 多檔案封存

// 建立 ZIP
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("archive.zip"))) {
    addToZip("file1.txt", zos);
    addToZip("dir/file2.txt", zos);
}

void addToZip(String path, ZipOutputStream zos) throws IOException {
    try (FileInputStream fis = new FileInputStream(path)) {
        zos.putNextEntry(new ZipEntry(path));
        byte[] buffer = new byte[1024];
        int len;
        while ((len = fis.read(buffer)) > 0) {
            zos.write(buffer, 0, len);
        }
        zos.closeEntry();
    }
}

3. 序列化物件壓縮儲存(節省磁碟空間)

// 寫入壓縮序列化物件
try (ObjectOutputStream oos = new ObjectOutputStream(
         new GZIPOutputStream(new FileOutputStream("obj.gz")))) {
    oos.writeObject(mySerializableObject);
}

// 讀取解壓縮還原
try (ObjectInputStream ois = new ObjectInputStream(
         new GZIPInputStream(new FileInputStream("obj.gz")))) {
    MyObject obj = (MyObject) ois.readObject();
}

五、客戶端/伺服器傳輸效能優化

在網路傳輸前壓縮資料,可大幅降低頻寬占用與延遲:

  • Client 端: 將請求物件序列化 → GZIP 壓縮 → 輸出至 Socket
  • Server 端: 從 Socket 讀取 → GZIP 解壓縮 → 反序列化物件
  • 適用場景: 大量資料傳輸、行動裝置弱網環境、Web Service 回應優化
// Client 發送壓縮資料
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
     GZIPOutputStream gzos = new GZIPOutputStream(baos);
     ObjectOutputStream oos = new ObjectOutputStream(gzos)) {
    oos.writeObject(requestObject);
    byte[] compressed = baos.toByteArray();
    socket.getOutputStream().write(compressed);
}

// Server 接收解壓縮
try (InputStream is = socket.getInputStream();
     GZIPInputStream gzis = new GZIPInputStream(is);
     ObjectInputStream ois = new ObjectInputStream(gzis)) {
    RequestObject req = (RequestObject) ois.readObject();
}

六、總結

java.util.zip 提供標準、高效的壓縮解決方案,無需外部工具即可在應用程式內部完成資料壓縮、解壓縮、校驗和計算。善用串流鏈結模式(GZIPOutputStream → ObjectOutputStream),可輕鬆實現物件序列化壓縮與網路傳輸優化,是 Java 開發者必備的工具箱技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved