代碼片段
private void zip(String zipFileName, File inputFile) throws Exception {
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
zip(out, inputFile, ""); // 第三個參數傳空字符串
out.close();
}
private void zip(ZipOutputStream out, File f, String base) throws Exception {
if (f.isDirectory()) {
File[] fl = f.listFiles();
out.putNextEntry(new ZipEntry(base + "/")); // 目錄條目以 / 結尾
base = base.length() == 0 ? "" : base + "/"; // 三目運算符處理路徑拼接
for (int i = 0; i < fl.length; i++) {
zip(out, fl[i], base + fl[i].getName()); // 遞歸:父路徑 + 文件名
}
} else {
out.putNextEntry(new ZipEntry(base)); // 文件條目
// ... 寫入文件內容
}
}
參數含義解析
| 參數 | 含義 | 初始值 | 遞歸變化 |
zipFileName | 輸出壓縮包路徑 | "hello.zip" | 不變 |
inputFile | 待壓縮文件/目錄 | new File("src") | 遞歸遍歷子文件 |
base | 壓縮包內相對路徑前綴 | "" (空字符串) | 逐層拼接:base + "/" + filename |
base 參數演示:壓縮 src 目錄
文件結構:
src/
├── Main.java
└── com/
└── example/
└── Util.java
調用: zip(out, new File("src"), "")
遞歸過程:
1. zip(src, base="")
- 是目錄 → putNextEntry("") → base = ""
- 遍歷 children:
2. zip(Main.java, base="" + "Main.java" = "Main.java")
- 是文件 → putNextEntry("Main.java")
3. zip(com, base="" + "com" = "com")
- 是目錄 → putNextEntry("com/") → base = "com/"
- 遍歷 children:
4. zip(example, base="com/" + "example" = "com/example")
- 是目錄 → putNextEntry("com/example/") → base = "com/example/"
- 遍歷 children:
5. zip(Util.java, base="com/example/" + "Util.java" = "com/example/Util.java")
- 是文件 → putNextEntry("com/example/Util.java")
壓縮包內結構:
Main.java
com/
└── example/
└── Util.java
關鍵代碼行解讀
// 三目運算符:如果 base 為空串,保持空串;否則加 "/"
base = base.length() == 0 ? "" : base + "/";
// 等價於:
if (base.isEmpty()) {
base = "";
} else {
base = base + "/";
}
// 作用:確保目錄條目以 "/" 結尾,文件條目不以 "/" 開頭
// 避免出現 "//Main.java" 或 "com//example" 這種雙斜杠
完整可運行工具類
import java.io.*;
import java.util.zip.*;
public class ZipUtil {
public static void zip(String zipFilePath, String sourcePath) throws IOException {
File sourceFile = new File(sourcePath);
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFilePath))) {
zip(zos, sourceFile, "");
}
}
private static void zip(ZipOutputStream zos, File file, String base) throws IOException {
if (file.isDirectory()) {
File[] children = file.listFiles();
if (children != null) {
// 目錄條目
if (!base.isEmpty()) {
zos.putNextEntry(new ZipEntry(base + "/"));
}
String newBase = base.isEmpty() ? "" : base + "/";
for (File child : children) {
zip(zos, child, newBase + child.getName());
}
}
} else {
// 文件條目
zos.putNextEntry(new ZipEntry(base));
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[8192];
int len;
while ((len = fis.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
}
zos.closeEntry();
}
}
public static void main(String[] args) throws IOException {
ZipUtil.zip("hello.zip", "src");
System.out.println("壓縮完成");
}
}
總結
- base = "":初始調用傳空串,表示壓縮包根目錄
- base 作用:記錄**壓縮包內部相對路徑**,遞歸時逐層拼接
- 三目運算符:處理路徑分隔符拼接,避免首個路徑以
/ 開頭或出現雙斜杠
- ZipEntry 規則:目錄以
/ 結尾,文件不以 / 開頭
- 上一篇文章: JavaScript 異步編程:回調函數模式解決 AJAX 返回值 undefined 問題
- 下一篇文章: HTML 圖片熱區映射:單張圖片不同區域顯示不同 title 提示文本
Copyright ©
程式碼之家 All Rights Reserved