Java zip檔案


Java對ZIP檔案格式有直接支援。通過使用java.util.zip包中的以下四個類來處理ZIP檔案格式:

  • ZipEntry
  • ZipInputStream
  • ZipOutputStream
  • ZipFile

ZipEntry物件表示ZIP檔案格式的歸檔檔案中的條目。zip條目可以是壓縮的或未壓縮的。ZipEntry類具有設定和獲取有關ZIP檔案中的條目的資訊的方法。ZipInputStream可以從每個條目的ZIP檔案讀取資料。
ZipOutputStream可以將資料寫入每個條目的ZIP檔案。ZipFile是一個從ZIP檔案讀取條目的實用程式類。
以下程式碼顯示如何建立ZIP檔案。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Main {
  public static void main(String[] args) {
    String zipFileName = "ziptest.zip";
    String[] entries = new String[2];
    entries[0] = "test1.txt";
    entries[1] = "notes" + File.separator + "test2.txt";
    zip(zipFileName, entries);
  }

  public static void zip(String zipFileName, String[] zipEntries) {

    try (ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(
        new FileOutputStream(zipFileName)))) {

      // Set the compression level to best compression
      zos.setLevel(Deflater.BEST_COMPRESSION);

      for (int i = 0; i < zipEntries.length; i++) {
        File entryFile = new File(zipEntries[i]);
        if (!entryFile.exists()) {
          System.out.println("The entry file  " + entryFile.getAbsolutePath()
              + "  does  not  exist");
          System.out.println("Aborted   processing.");
          return;
        }
        ZipEntry ze = new ZipEntry(zipEntries[i]);
        zos.putNextEntry(ze);
        addEntryContent(zos, zipEntries[i]);
        zos.closeEntry();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public static void addEntryContent(ZipOutputStream zos, String entryFileName)
      throws IOException, FileNotFoundException {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
        entryFileName));

    byte[] buffer = new byte[1024];
    int count = -1;
    while ((count = bis.read(buffer)) != -1) {
      zos.write(buffer, 0, count);
    }
    bis.close();
  }
}

上面的程式碼生成以下結果。

The entry file  F:\website\yiibai\worksp\test1.txt  does  not  exist
Aborted   processing.

讀取Zip檔案

以下程式碼顯示如何讀取ZIP檔案的內容。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class Main {
  public static void main(String[] args) {
    String zipFileName = "ziptest.zip";
    String unzipdirectory = "extracted";
    unzip(zipFileName, unzipdirectory);
  }

  public static void unzip(String zipFileName, String unzipdir) {
    try (ZipInputStream zis = new ZipInputStream(new BufferedInputStream(
        new FileInputStream(zipFileName)))) {

      ZipEntry entry = null;
      while ((entry = zis.getNextEntry()) != null) {
        // Extract teh entry's contents 
        extractEntryContent(zis, entry, unzipdir);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public static void extractEntryContent(ZipInputStream zis, ZipEntry entry,
      String unzipdir) throws IOException, FileNotFoundException {

    String entryFileName = entry.getName();
    String entryPath = unzipdir + File.separator + entryFileName;

    createFile(entryPath);

    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(
        entryPath));

    byte[] buffer = new byte[1024];
    int count = -1;
    while ((count = zis.read(buffer)) != -1) {
      bos.write(buffer, 0, count);
    }

    bos.close();
  }

  public static void createFile(String filePath) throws IOException {
    File file = new File(filePath);
    File parent = file.getParentFile();

    if (!parent.exists()) {
      parent.mkdirs();
    }
    file.createNewFile();
  }
}

範例-2

下面的程式碼顯示了如何使用ZipFile類。當想在ZIP檔案中列出條目時,ZipFile類派上用場。

import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class Main {
  public static void main(String[] args) throws Exception {
    ZipFile zf = new ZipFile("ziptest.zip");

    // Get the enumeration for all zip entries and loop through them
    Enumeration<? extends ZipEntry> e = zf.entries();
    ZipEntry entry = null;

    while (e.hasMoreElements()) {
      entry = e.nextElement();

      // Get the input stream for the current zip entry
      InputStream is = zf.getInputStream(entry);

      /* Read data for the entry using the is object */

      // Print the name of the entry
      System.out.println(entry.getName());
    }

  }
}

以下程式碼使用Stream類和lambda表示式重寫上述程式碼。

import java.io.IOException;
import java.io.InputStream;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class Main {
  public static void main(String[] args) throws Exception {
    ZipFile zf = new ZipFile("ziptest.zip");

    Stream<? extends ZipEntry> entryStream = zf.stream();
    entryStream.forEach(entry -> {
      try {
        // Get the input stream for the current zip entry
        InputStream is = zf.getInputStream(entry);
        System.out.println(entry.getName());
      } catch (IOException e) {
        e.printStackTrace();
      }

    });
  }
}

GZIPInputStreamGZIPOutputStream類用於處理GZIP檔案格式。