Programmering

Java Tips 49: Hvordan trekke ut Java-ressurser fra JAR og zip-arkiver

De fleste Java-programmerere er ganske klare på fordelene ved å bruke en JAR-fil til å samle alle de forskjellige ressursene (det vil si .klassfiler, lyder og bilder) som inneholder Java-løsningen. (Hvis du ikke er kjent med JAR-filer, kan du sjekke ressursseksjonen nedenfor.) Et veldig vanlig spørsmål som stilles av folk som nettopp har begynt å innlemme JAR-filer i triksposen, er: "Hvordan trekker jeg ut et bilde fra KRUKKE?" Vi skal svare på det spørsmålet og gi en klasse som gjør det superenkelt å hente ut en ressurs fra en JAR!

Laster inn et GIF-bilde

La oss si at vi har en JAR-fil som inneholder en rekke .gif-bildefiler som vi vil bruke i applikasjonen vår. Slik får vi tilgang til en bildefil fra JAR ved hjelp av JarResources:

 JarResources jar = nye JarResources ("Images.jar"); Bildelogo = Toolkit.getDefaultToolkit (). CreateImage (jar.getResource ("logo.gif"); 

Den kodebiten viser at vi kan lage en JarResources objekt initialisert til JAR-filen som inneholder ressursen vi er interessert i å bruke - Images.jar. Vi bruker deretter JarResources 'getResource () metode for å gi rådata fra logo.gif-filen for AWT-verktøykassen createImage () metode.

Et notat om navngivning

JarResource er et ganske greit eksempel på hvordan du bruker forskjellige fasiliteter som tilbys av Java 1.1 for å manipulere JAR og zip arkivfiler.

Et raskt notat om navngivning. Arkiveringsstøtte i Java startet faktisk med det populære zip-arkiveringsformatet (sjekk ut "Java Tips 21: Bruk arkivfiler for å øke hastigheten på innlasting av applet"). Så, opprinnelig, ved implementering av Java-støtte for å manipulere arkivfilene, ble alle klassene og hva som helst plassert i pakken java.util.zip; disse klassene pleier å begynne med "Glidelås. "Men et sted i flyttingen til Java 1.1, er maktene som endres navnet på arkivet for å være mer Java-fokuserte. Derfor er det vi nå kaller JAR-filer i utgangspunktet zip-filer.

Hvordan det fungerer

De viktige datafeltene for JarResources klasse brukes til å spore og lagre innholdet i den spesifiserte JAR-filen:

offentlig sluttklasse JarResources {public boolean debugOn = false; private Hashtable htSizes = ny Hashtable (); private Hashtable htJarContents = ny Hashtable (); privat streng jarFileName; 

Så, instantiering av klassen setter navnet på JAR-filen og ringer deretter til i det() metode for å gjøre alt ekte arbeid:

 offentlige JarResources (streng jarFileName) {this.jarFileName = jarFileName; i det(); } 

Nå, den i det() metoden laster stort sett bare hele innholdet i den spesifiserte JAR-filen i en hashtable (tilgjengelig via navnet på ressursen).

Dette er en ganske heftig metode, så la oss bryte den ned litt lenger. De ZipFile klasse gir oss grunnleggende tilgang til informasjonen om JAR / zip arkivhode. Dette ligner på kataloginformasjonen i et filsystem. Her oppregner vi gjennom alle oppføringene i ZipFile og bygge ut htStørrelser hashtable med størrelsen på hver ressurs i arkivet:

 privat ugyldig init () {prøv {ZipFile zf = new ZipFile (jarFileName); Oppregning e = zf.entries (); mens (e.hasMoreElements ()) {ZipEntry ze = (ZipEntry) e.nextElement (); hvis (debugOn) {System.out.println (dumpZipEntry (ze)); } htSizes.put (ze.getName (), nytt heltal ((int) ze.getSize ())); } zf.close (); 

Deretter får vi tilgang til arkivet ved bruk av ZipInputStream klasse. De ZipInputStream klasse gjør alt det magiske for å tillate oss å lese hver av de individuelle ressursene i arkivet. Vi leser nøyaktig antall byte fra arkivet som består av hver ressurs og lagrer dataene i htJarContents hashtable tilgjengelig med ressursnavn:

 FileInputStream fis = ny FileInputStream (jarFileName); BufferedInputStream bis = new BufferedInputStream (fis); ZipInputStream zis = ny ZipInputStream (bis); ZipEntry ze = null; mens ((ze = zis.getNextEntry ())! = null) {hvis (ze.isDirectory ()) {fortsetter; } if (debugOn) {System.out.println ("ze.getName () =" + ze.getName () + "," + "getSize () =" + ze.getSize ()); } int størrelse = (int) ze.getSize (); // -1 betyr ukjent størrelse. if (size == - 1) {size = ((Integer) htSizes.get (ze.getName ())). intValue (); } byte [] b = ny byte [(int) størrelse]; int rb = 0; int klump = 0; mens (((int) size - rb)> 0) {chunk = zis.read (b, rb, (int) size - rb); hvis (klump == - 1) {pause; } rb + = klump; } // legg til den interne ressurshashtabellen htJarContents.put (ze.getName (), b); if (debugOn) {System.out.println (ze.getName () + "rb =" + rb + ", size =" + size + ", csize =" + ze.getCompressedSize ()); }}} fangst (NullPointerException e) {System.out.println ("gjort."); } fange (FileNotFoundException e) {e.printStackTrace (); } fange (IOException e) {e.printStackTrace (); }} 

Merk at navnet som brukes til å identifisere hver ressurs, er det kvalifiserte banenavnet til ressursen i arkivet, ikke, for eksempel navnet på en klasse i en pakke - det vil si ZipEntry klasse fra java.util.zip-pakken vil hete "java / util / zip / ZipEntry", i stedet for "java.util.zip.ZipEntry."

Den siste viktige delen av koden er den enkle testdriveren. Testdriveren er et enkelt program som tar et JAR / zip-arkivnavn og navnet på en ressurs. Den prøver å finne ressursen i arkivet og rapporterer suksess eller fiasko:

 public static void main (String [] args) kaster IOException {if (args.length! = 2) {System.err.println ("bruk: java JarResources"); System.exit (1); } JarResources jr = nye JarResources (args [0]); byte [] buff = jr.getResource (args [1]); if (buff == null) {System.out.println ("Kunne ikke finne" + args [1] + "."); } annet {System.out.println ("Fant" + args [1] + "(lengde =" + buff.lengde + ")."); }}} // Slutt på JarResources-klassen. 

Og der har du det. En brukervennlig klasse som skjuler alt rotet som er involvert i å bruke ressurser gjemt i JAR-filer.

Øvelser for leseren

Nå som du har sansen for å trekke ut ressurser fra en arkivfil, er det noen retninger du kanskje vil utforske når du endrer og utvider JarResources klasse:

  • I stedet for å laste alt under konstruksjonen, gjør forsinket lasting. I tilfelle en stor JAR-fil kan det hende at det ikke er nok minne til å laste alle filene under konstruksjon.
  • I stedet for bare å gi en generisk tilgangsmetode som getResource (), kan vi tilby andre ressursspesifikke tilbehør - for eksempel getImage (), som returnerer en Java Bilde gjenstand, getClass (), som returnerer en Java Klasse objekt (med hjelp fra en tilpasset klasselaster), og så videre. Hvis JAR-filen er liten nok, kan vi forhåndsbygge alle ressursene basert på utvidelsene deres (.gif, .class og så videre).
  • Noen metoder bør gi informasjon om den gitte JAR-filen i seg selv (i utgangspunktet en omslag rundt ZipFile), inkludert: antall Jar / zip-oppføringer; en teller som returnerer alle navnene på ressursene; aksessorer som returnerer lengden (og andre attributter) til en bestemt oppføring; og en accessor som tillater indeksering, for å nevne noen.
  • JarResources kan utvides til å brukes av applets. Ved å bruke appletparametere og URLtilkobling klasse kan JAR-innholdet lastes ned fra nettverket i stedet for å åpne arkivene som lokale filer. Videre kan vi utvide denne klassen som en tilpasset Java-innholdshåndterer.

Konklusjon

Hvis du har vært ivrig etter å vite hvordan du trekker ut et bilde fra en JAR-fil, har du nå en måte. Ikke bare kan du håndtere bilder med en JAR-fil, men med den nye klassen som er gitt i dette tipset, jobber du med å trekke ut magi på noen ressurs fra en JAR.

Arthur Choi jobber for tiden for IBM som en rådgivende programmerer. Han har jobbet for flere selskaper, inkludert SamSung Network Laboratory og MITRE. De forskjellige prosjektene han har jobbet med er klient / server-systemer, databehandling av distribuerte objekter og nettverksadministrasjon. Han har brukt en rekke språk i ulike operativsystemmiljøer. Han begynte å programmere i 1981 med FORTRAN IV og COBOL. Senere byttet han til C og C ++, og han har jobbet med Java i omtrent to år. Han er mest interessert i applikasjoner av Java innen områdene datalagre gjennom brednettnettverk, og parallell og distribuert behandling via Internett (ved hjelp av agentbasert programmering). John Mitchell, ansatt, konsulent og rektor i sitt eget selskap, har investert de siste ti årene i utvikling av banebrytende programvare, og i rådgivning og opplæring av andre utviklere. Han har gitt rådgivning om Java-teknologi, kompilatorer, tolker, nettbaserte applikasjoner og Internett-handel. John var medforfatter av Making Sense of Java: A Guide for Managers and the Rest of Us og har publisert artikler i programmeringstidsskrifter. I tillegg til å skrive Java Tips-kolonnen for JavaWorld, modererer han nyhetsgruppene comp.lang.tcl.announce og comp.binaries.geos.

Lær mer om dette emnet

  • Her er klassefilen JarResources.java //www.javaworld.com/javatips/javatip49/JarResources.java
  • JAR //www.javasoft.com/products/jdk/1.1/docs/guide/jar/index.html
  • For mer informasjon om arkiveringsstøtte i Java, se "Java Tips 21Bruk arkivfiler for å øke hastigheten på innlasting av applet" //www.javaworld.com/javatips/jw-javatip21.html

Denne historien, "Java Tips 49: How to extract Java resources from JAR and zip archives" ble opprinnelig utgitt av JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found