JAR 檔案打包 .class、圖片、聲音等資源是 Java 開發常識,但新手常問:「如何從 JAR 取出圖片?」本文提供完整解決方案與通用 JarResources 工具類,支援提取 JAR/ZIP 內任意資源。
JarResources jr = new JarResources("GifBundle.jar");
Image logo = Toolkit.getDefaultToolkit().createImage(jr.getResource("logo.gif"));
建立 JarResources 實例指定 JAR 檔,呼叫 getResource() 取得位元組陣列,傳給 AWT Toolkit.createImage() 即可建立圖片物件。
public final class JarResources {
public boolean debugOn = false;
private Hashtable htSizes = new Hashtable(); // 資源名稱 -> 大小
private Hashtable htJarContents = new Hashtable(); // 資源名稱 -> 位元組陣列
private String jarFileName;
// ...
}
ZipFile 列舉所有條目,填入 htSizesZipInputStream 逐一讀取各資源完整位元組,存入 htJarContentsprivate 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)。
// 取得資源位元組陣列
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; 直接跳過目錄條目,需增強遞迴處理JarResources 封裝了 JAR/ZIP 資源提取的複雜細節,讓開發者專注於業務邏輯。不僅限於圖片,適用於任何打包在 JAR 中的資源(類別檔、配置檔、媒體檔等)。掌握此技巧,靈活運用 JAR 資源管理優勢。