ZipOutputStream:寫入 ZIP 格式資料流ZipEntry:代表壓縮檔內單一項目(檔案/目錄)FileInputStream:讀取來源檔案
import java.io.*;
import java.util.zip.*;
public class ZipCreator {
public static void main(String[] args) throws IOException {
if (args.length == 0) {
System.err.println("用法: java ZipCreator <檔案1> [檔案2] ...");
return;
}
byte[] buffer = new byte[512];
// 輸出至標準輸出,實際應用可改為 new FileOutputStream("output.zip")
ZipOutputStream zout = new ZipOutputStream(System.out);
for (String filePath : args) {
FileInputStream in = new FileInputStream(filePath);
// ZipEntry 名稱使用正斜線分隔,跨平台相容
ZipEntry entry = new ZipEntry(filePath.replace(File.separatorChar, '/'));
zout.putNextEntry(entry);
int len;
while ((len = in.read(buffer)) != -1) {
zout.write(buffer, 0, len);
}
zout.closeEntry();
in.close();
printEntryInfo(entry);
}
zout.close();
}
private static void printEntryInfo(ZipEntry e) {
PrintStream err = System.err;
err.print("added " + e.getName());
if (e.getMethod() == ZipEntry.DEFLATED) {
long size = e.getSize();
if (size > 0) {
long csize = e.getCompressedSize();
long ratio = ((size - csize) * 100) / size;
err.println(" (deflated " + ratio + "%)");
} else {
err.println(" (deflated 0%)");
}
} else {
err.println(" (stored 0%)");
}
}
}
512 bytes 為示範用較小值,實際建議 4096 或 8192(8KB)提升 I/O 效能。
new ZipEntry(filePath.replace(File.separatorChar, '/'))
ZIP 規範要求使用正斜線 / 作為路徑分隔,Windows 反斜線需轉換,確保跨平台解壓相容。
DEFLATED:標準壓縮(預設)STORED:僅存儲不壓縮(原大小 - 壓縮後大小) * 100 / 原大小若需包含目錄結構,需顯式建立以 / 結尾的 ZipEntry:
ZipEntry dirEntry = new ZipEntry("mydir/");
zout.putNextEntry(dirEntry);
zout.closeEntry(); // 目錄項目無資料內容
public static void zipDirectory(File dir, ZipOutputStream zout, String basePath) throws IOException {
File[] files = dir.listFiles();
if (files == null) return;
for (File file : files) {
String entryName = basePath + file.getName();
if (file.isDirectory()) {
zipDirectory(file, zout, entryName + "/");
} else {
ZipEntry entry = new ZipEntry(entryName);
zout.putNextEntry(entry);
try (FileInputStream in = new FileInputStream(file)) {
byte[] buf = new byte[8192];
int len;
while ((len = in.read(buf)) != -1) {
zout.write(buf, 0, len);
}
}
zout.closeEntry();
}
}
}
try (ZipOutputStream zout = new ZipOutputStream(new FileOutputStream("out.zip"));
FileInputStream in = new FileInputStream(file)) {
zout.putNextEntry(new ZipEntry(entryName));
byte[] buf = new byte[8192];
int len;
while ((len = in.read(buf)) != -1) {
zout.write(buf, 0, len);
}
zout.closeEntry();
} // 自動關閉 zout、in
| 問題 | 原因 | 解決 |
|---|---|---|
| 中文檔名解壓亂碼 | ZIP 標準未規定編碼,各工具預設不同 | 使用 Apache Commons Compress 指定 UTF-8,或 JDK 7+ ZipFile(Charset) |
| 大檔案記憶體不足 | 一次讀入整個檔案 | 分塊流式讀寫(如上範例) |
| 空目錄不見 | ZipEntry 僅含檔案 | 顯式建立目錄 Entry |