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

從 JAR/ZIP 檔案提取 Java 資源完整指南:JarResources 工具類實作

     編輯:Java 相關知識

前言

JAR 檔案打包 .class、圖片、聲音等資源是 Java 開發常識,但新手常問:「如何從 JAR 取出圖片?」本文提供完整解決方案與通用 JarResources 工具類,支援提取 JAR/ZIP 內任意資源。

快速上手:載入 GIF 圖片範例

JarResources jr = new JarResources("GifBundle.jar");
Image logo = Toolkit.getDefaultToolkit().createImage(jr.getResource("logo.gif"));

建立 JarResources 實例指定 JAR 檔,呼叫 getResource() 取得位元組陣列,傳給 AWT Toolkit.createImage() 即可建立圖片物件。

JarResources 核心設計

關鍵資料結構

public final class JarResources {
    public boolean debugOn = false;
    private Hashtable htSizes = new Hashtable();       // 資源名稱 -> 大小
    private Hashtable htJarContents = new Hashtable(); // 資源名稱 -> 位元組陣列
    private String jarFileName;
    // ...
}

初始化流程:兩階段讀取

  1. 掃描大小:使用 ZipFile 列舉所有條目,填入 htSizes
  2. 提取內容:使用 ZipInputStream 逐一讀取各資源完整位元組,存入 htJarContents
private void init() {
    try {
        // 階段 1:取得大小
        ZipFile zf = new ZipFile(jarFileName);
        Enumeration e = zf.entries();
        while (e.hasMoreElements()) {
            ZipEntry ze = (ZipEntry) e.nextElement();
            htSizes.put(ze.getName(), new Integer((int) ze.getSize()));
        }
        zf.close();

        // 階段 2:提取資源
        FileInputStream fis = new FileInputStream(jarFileName);
        BufferedInputStream bis = new BufferedInputStream(fis);
        ZipInputStream zis = new ZipInputStream(bis);
        ZipEntry ze;
        while ((ze = zis.getNextEntry()) != null) {
            if (ze.isDirectory()) continue; // 注意:不處理子目錄資源
            int size = (int) ze.getSize();
            if (size == -1) size = ((Integer) htSizes.get(ze.getName())).intValue();
            byte[] b = new byte[size];
            int rb = 0, chunk;
            while ((size - rb) > 0) {
                chunk = zis.read(b, rb, size - rb);
                if (chunk == -1) break;
                rb += chunk;
            }
            htJarContents.put(ze.getName(), b);
        }
    } catch (Exception ex) { ex.printStackTrace(); }
}

資源命名規則

鍵值為 ZIP 條目完整路徑名,如 java/util/zip/ZipEntry(非 java.util.zip.ZipEntry)。

公開 API

// 取得資源位元組陣列
public byte[] getResource(String name) {
    return (byte[]) htJarContents.get(name);
}

// 除錯用:輸出 ZipEntry 資訊
private String dumpZipEntry(ZipEntry ze) { /* ... */ }

測試驅動程式

public static void main(String[] args) throws IOException {
    if (args.length != 2) {
        System.err.println("usage: java JarResources  ");
        System.exit(1);
    }
    JarResources jr = new JarResources(args[0]);
    byte[] buff = jr.getResource(args[1]);
    if (buff == null)
        System.out.println("Could not find " + args[1] + ".");
    else
        System.out.println("Found " + args[1] + " (length=" + buff.length + ").");
}

已知限制與改進方向

  • 不支援子目錄遞迴:程式碼中 if (ze.isDirectory()) continue; 直接跳過目錄條目,需增強遞迴處理
  • 記憶體一次載入全 JAR:大型 JAR 可能造成 OOM,可改為隨取隨讀模式
  • 未關閉所有流:異常路徑下資源洩漏風險,建議使用 try-with-resources(Java 7+)

總結

JarResources 封裝了 JAR/ZIP 資源提取的複雜細節,讓開發者專注於業務邏輯。不僅限於圖片,適用於任何打包在 JAR 中的資源(類別檔、配置檔、媒體檔等)。掌握此技巧,靈活運用 JAR 資源管理優勢。

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