首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java 讀取 ZIP/JAR 內嵌套條目:正確路徑寫法與 ZipEntry 陷阱

     編輯:程式設計疑難解答

問題現場

需從 APK/JAR 中讀取 `META-INF/CERT.RSA` 簽名文件,代碼嘗試:


ZipEntry entry = new ZipEntry("META-INF/"); // 錯誤:以 / 結尾視為目錄
InputStream in = zipFile.getInputStream(entry); // 返回 null 或拋異常

根本原因

  • ZipEntry 名稱**區分大小寫**,必須與壓縮包內部路徑**完全一致**。
  • 目錄項以 `/` 結尾,**不是文件**,無法獲取輸入流。
  • 正確文件路徑:META-INF/CERT.RSA(無前導 `/`,無尾隨 `/`)。

正確代碼模板


public static InputStream getCertInputStream(String apkPath) {
    try (ZipFile zipFile = new ZipFile(apkPath)) {
        // 1. 精確匹配文件名(區分大小寫)
        ZipEntry entry = zipFile.getEntry("META-INF/CERT.RSA");
        if (entry == null) {
            // 兼容小寫/其他簽名文件
            entry = zipFile.getEntry("META-INF/CERT.SF");
        }
        if (entry == null) return null;
        return zipFile.getInputStream(entry); // 返回流,調用者負責關閉
    } catch (IOException e) {
        log.error("Read cert failed", e);
        return null;
    }
}

進階:遍歷查找所有簽名文件


Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
    ZipEntry e = entries.nextElement();
    String name = e.getName();
    if (name.startsWith("META-INF/") && (name.endsWith(".RSA") || name.endsWith(".DSA") || name.endsWith(".EC"))) {
        // 找到簽名塊文件
        try (InputStream is = zipFile.getInputStream(e)) {
            // 解析 PKCS7...
        }
    }
}

關鍵注意點

陷阱正確做法
手動 `new ZipEntry("path")`用 `zipFile.getEntry("path")` 獲取實際條目對象(含壓縮信息、CRC、時間戳)
路徑分隔符用 `\`ZIP 規範強制 `/`,跨平台統一用 `/`
忽略大小寫Linux/APK 區分大小寫,需精確匹配或遍歷過濾
流未關閉用 try-with-resources 自動關閉 ZipFile 與 InputStream

總結

讀取 ZIP 內嵌套文件核心三要素:**精確路徑 (區分大小寫)、用 `getEntry` 而非 `new ZipEntry`、try-with-resources 管理資源**。`META-INF/CERT.RSA` 是 APK 簽名驗證的標準入口,路徑寫對是成功第一步。

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