Programování

Tip 49 pro Javu: Jak extrahovat prostředky Java z archivů JAR a ZIP

Většina programátorů v Javě si docela jasně uvědomuje výhody používání souboru JAR ke sdružování všech různých zdrojů (tj. Souborů .class, zvuků a obrázků), které tvoří jejich řešení Java. (Pokud nejste obeznámeni se soubory JAR, podívejte se do sekce Zdroje níže.) Velmi častá otázka lidí, kteří právě začínají začleňovat soubory JAR do své tašky triků, je: „Jak extrahuji obrázek z SKLENICE?" Odpovíme na tuto otázku a poskytneme třídu, díky níž bude extrahování jakéhokoli zdroje z JAR super jednoduché!

Načítání obrázku GIF

Řekněme, že máme soubor JAR obsahující spoustu obrázkových souborů .gif, které chceme použít v naší aplikaci. Zde je návod, jak bychom mohli získat přístup k obrazovému souboru z JAR pomocí JarResources:

 JarResources jar = new JarResources ("Images.jar"); Logo obrázku = Toolkit.getDefaultToolkit (). CreateImage (jar.getResource ("logo.gif"); 

Tento fragment kódu ukazuje, že můžeme vytvořit a JarResources objekt inicializovaný do souboru JAR obsahující prostředek, který máme zájem použít - Images.jar. Poté použijeme JarResources 'getResource () metoda pro poskytnutí nezpracovaných dat ze souboru logo.gif pro sadu nástrojů AWT createImage () metoda.

Poznámka k pojmenování

JarResource je rozumně přímým příkladem toho, jak používat různé prostředky poskytované prostředím Java 1.1 k manipulaci s archivními soubory JAR a zip.

Rychlá poznámka o pojmenování. Podpora archivace v Javě skutečně začala pomocí populárního formátu archivace zipu (podívejte se na „Java Tip 21: Použití archivních souborů k urychlení načítání appletu“). Takže původně při implementaci podpory Javy pro manipulaci s archivními soubory byly všechny třídy a co nebylo umístěno v balíčku java.util.zip; tyto třídy mají sklon začínat „Zip. "Ale někde v přechodu na Javu 1.1 jsou pravomoci, které změnily název archivu, více zaměřeny na Javu. Proto nyní nazýváme soubory JAR v zásadě soubory zip.

Jak to funguje

Důležitá datová pole pro JarResources třídy se používají ke sledování a ukládání obsahu zadaného souboru JAR:

public final class JarResources {public boolean debugOn = false; private Hashtable htSizes = new Hashtable (); private Hashtable htJarContents = new Hashtable (); private String jarFileName; 

Instance třídy tedy nastaví název souboru JAR a poté zavolá na init () metoda k provedení veškeré skutečné práce:

 public JarResources (String jarFileName) {this.jarFileName = jarFileName; init (); } 

Nyní init () metoda v podstatě jen načte celý obsah zadaného souboru JAR do hashtable (přístupné přes název zdroje).

Jedná se o poměrně těžkou metodu, takže ji pojďme rozebrat o něco dále. The ZipFile třída nám poskytuje základní přístup k informacím záhlaví archivu JAR / zip. To je podobné informacím o adresáři v systému souborů. Zde uvádíme výčet všech položek v souboru ZipFile a vybudovat htVelikosti hashtable s velikostí každého zdroje v archivu:

 private void init () {try {ZipFile zf = new ZipFile (jarFileName); Výčet e = zf.entries (); while (e.hasMoreElements ()) {ZipEntry ze = (ZipEntry) e.nextElement (); if (debugOn) {System.out.println (dumpZipEntry (ze)); } htSizes.put (ze.getName (), new Integer ((int) ze.getSize ())); } zf.close (); 

Dále přistupujeme k archivu pomocí ZipInputStream třída. The ZipInputStream třída dělá všechna kouzla, aby nám umožnila přečíst každý z jednotlivých zdrojů v archivu. Čteme přesný počet bajtů z archivu, který obsahuje každý zdroj, a ukládáme tato data do htJarContents hashtable přístupný podle názvu zdroje:

 FileInputStream fis = nový FileInputStream (jarFileName); BufferedInputStream bis = nový BufferedInputStream (fis); ZipInputStream zis = nový ZipInputStream (bis); ZipEntry ze = null; while ((ze = zis.getNextEntry ())! = null) {if (ze.isDirectory ()) {continue; } if (debugOn) {System.out.println ("ze.getName () =" + ze.getName () + "," + "getSize () =" + ze.getSize ()); } int size = (int) ze.getSize (); // -1 znamená neznámou velikost. if (size == - 1) {size = ((Integer) htSizes.get (ze.getName ())). intValue (); } byte [] b = nový bajt [(int) velikost]; int rb = 0; int blok = 0; while (((int) size - rb)> 0) {chunk = zis.read (b, rb, (int) size - rb); if (chunk == - 1) {break; } rb + = kus; } // přidat do interního hashtable zdroje htJarContents.put (ze.getName (), b); if (debugOn) {System.out.println (ze.getName () + "rb =" + rb + ", size =" + size + ", csize =" + ze.getCompressedSize ()); }}} catch (NullPointerException e) {System.out.println ("hotovo."); } catch (FileNotFoundException e) {e.printStackTrace (); } catch (IOException e) {e.printStackTrace (); }} 

Všimněte si, že název používaný k identifikaci každého prostředku je kvalifikovaný název cesty prostředku v archivu, ne, například název třídy v balíčku - tj ZipEntry třída z balíčku java.util.zip by byla pojmenována „java / util / zip / ZipEntry“, spíše než „java.util.zip.ZipEntry.“

Poslední důležitou součástí kódu je jednoduchý testovací ovladač. Testovací ovladač je jednoduchá aplikace, která přebírá název archivu JAR / zip a název prostředku. Pokouší se najít zdroj v archivu a nahlásí jeho úspěch nebo neúspěch:

 public static void main (String [] args) hodí IOException {if (args.length! = 2) {System.err.println ("usage: java JarResources"); System.exit (1); } JarResources jr = nové JarResources (args [0]); byte [] buff = jr.getResource (args [1]); if (buff == null) {System.out.println ("Nelze najít" + args [1] + "."); } else {System.out.println ("Nalezeno" + args [1] + "(length =" + buff.length + ")."); }}} // Konec třídy JarResources. 

A tady to máte. Snadno použitelná třída, která skrývá veškerou nepořádek spojený s používáním zdrojů zastrčených v souborech JAR.

Cvičení pro čtenáře

Nyní, když máte pocit, že chcete extrahovat zdroje z archivního souboru, je zde několik pokynů, které byste mohli chtít prozkoumat při úpravách a rozšiřování JarResources třída:

  • Namísto načítání všeho během výstavby proveďte zpožděné načítání. V případě velkého souboru JAR nemusí být dostatek paměti k načtení všech souborů během výstavby.
  • Místo jednoduchého poskytnutí obecné metody přístupového typu jako getResource (), mohli bychom poskytnout další přístupové zdroje specifické pro zdroje - například getImage (), který vrací Java obraz objekt, getClass (), který vrací Java Třída objekt (s pomocí přizpůsobeného zavaděče tříd) atd. Pokud je soubor JAR dostatečně malý, mohli bychom předem sestavit všechny zdroje na základě jejich přípon (.gif, .class atd.).
  • Některé metody by měly poskytovat informace o samotném daném souboru JAR (v zásadě souhrnný popis) ZipFile), včetně: počtu položek Jar / zip; enumerátor, který vrací všechny názvy prostředků; přístupové objekty, které vracejí délku (a další atributy) konkrétní položky; a přístupový modul, který umožňuje indexování, abychom jmenovali alespoň některé.
  • JarResources lze rozšířit pro použití applety. Využitím parametrů appletu a URLConnection třídy, lze obsah JAR stáhnout ze sítě namísto otevírání archivů jako lokálních souborů. Dále můžeme tuto třídu rozšířit jako vlastní obslužnou rutinu obsahu Java.

Závěr

Pokud jste toužili vědět, jak extrahovat obrázek ze souboru JAR, nyní máte způsob. Nejen, že můžete manipulovat s obrázky pomocí souboru JAR, ale s novou třídou uvedenou v tomto tipu budete pracovat se svou extrakční magií na žádný zdroj z JAR.

Arthur Choi v současné době pracuje pro IBM jako poradní programátor. Pracoval pro několik společností, včetně SamSung Network Laboratory a MITER. Různé projekty, na kterých pracoval, jsou systémy klient / server, výpočet distribuovaných objektů a správa sítě. Používal řadu jazyků v různých prostředích operačního systému. Programování zahájil v roce 1981 pomocí FORTRAN IV a COBOL. Později přešel na C a C ++ a s Javou pracuje zhruba dva roky. Nejvíc se zajímá o aplikace Java v oblastech datových úložišť prostřednictvím rozsáhlých sítí a paralelního a distribuovaného zpracování přes internet (pomocí programování na bázi agentů). John Mitchell, zaměstnanec, konzultant a ředitel své vlastní společnosti, investoval posledních deset let do vývoje špičkového počítačového softwaru a do poradenství a školení dalších vývojářů. Poskytoval poradenství v oblasti technologie Java, překladačů, tlumočníků, webových aplikací a internetového obchodu. John spoluautorem Making Sense of Java: A Guide for Managers and the Rest of Us a publikoval články v programovacích časopisech. Kromě psaní sloupce Tipy pro Java pro JavaWorld moderuje diskusní skupiny comp.lang.tcl.announce a comp.binaries.geos.

Další informace o tomto tématu

  • Tady je soubor třídy JarResources.java //www.javaworld.com/javatips/javatip49/JarResources.java
  • JAR //www.javasoft.com/products/jdk/1.1/docs/guide/jar/index.html
  • Další informace o podpoře archivace v Javě najdete v části „Java Tip 21Použití archivních souborů k urychlení načítání appletu“ //www.javaworld.com/javatips/jw-javatip21.html

Tento příběh, „Tip Java 49: Jak extrahovat zdroje Java z archivů JAR a zip“, původně publikoval JavaWorld.