Ohjelmointi

Java-vinkki 49: Java-resurssien purkaminen JAR- ja zip-arkistoista

Suurimmalla osalla Java-ohjelmoijista on melko selvät edut, jotka liittyvät JAR-tiedoston käyttämiseen kaikkien niiden Java-ratkaisun sisältävien resurssien (eli .class-tiedostojen, äänien ja kuvien) niputtamiseen. (Jos et ole perehtynyt JAR-tiedostoihin, tutustu alla olevaan Resurssit-osioon.) Hyvin yleinen kysymys, jonka ihmiset, jotka ovat vasta aloittamassa JAR-tiedostojen sisällyttämistä temppupussiinsa, on: "Kuinka otan kuvan JAR? " Vastaamme tähän kysymykseen ja tarjoamme luokan, jonka avulla resurssien poimiminen JAR: sta on erittäin helppoa!

Ladataan GIF-kuvaa

Oletetaan, että meillä on JAR-tiedosto, joka sisältää joukon .gif-kuvatiedostoja, joita haluamme käyttää sovelluksessamme. Näin pääsimme kuvatiedostoon JAR: sta käyttämällä JarResources:

 JarResources jar = new JarResources ("Images.jar"); Kuvalogo = Toolkit.getDefaultToolkit (). CreateImage (jar.getResource ("logo.gif"); 

Tämä koodinpätkä osoittaa, että voimme luoda JarResources objekti alustettiin JAR-tiedostoon, joka sisältää resurssin, jota olemme kiinnostuneita käyttämään - Images.jar. Sitten käytämme JarResources 'getResource () tapa antaa raakatiedot logo.gif-tiedostosta AWT-työkalupakille createImage () menetelmä.

Huomautus nimeämisestä

JarResource on kohtuullisen yksinkertainen esimerkki siitä, miten Java 1.1: n tarjoamia erilaisia ​​toimintoja voidaan käyttää JAR- ja zip-arkistotiedostojen käsittelyyn.

Nopea huomautus nimeämisestä. Arkistointituki Java-ohjelmassa alkoi todella käyttää suosittua zip-arkistointimuotoa (katso "Java Tip 21: Käytä arkistotiedostoja appletien lataamisen nopeuttamiseksi"). Joten alun perin Java-tuen toteuttamisessa arkistotiedostojen manipuloimiseksi kaikki luokat ja mikä tahansa muu sijoittettiin java.util.zip-pakettiin; nämä luokat alkavat yleensä "Postinumero"Mutta jossain siirryttäessä Java 1.1: een voimat, jotka muuttavat arkiston nimen entistä Java-keskittyneemmiksi. Siksi, mitä nyt kutsumme JAR-tiedostoiksi, ovat pohjimmiltaan zip-tiedostot.

Kuinka se toimii

Tärkeät tietokentät JarResources luokan avulla seurataan ja tallennetaan määritetyn JAR-tiedoston sisältöä:

public final class JarResources {public boolean debugOn = false; yksityinen hashtable htSizes = uusi hashtable (); yksityinen hashtable htJarContents = uusi hashtable (); yksityinen merkkijono jarFileName; 

Joten luokan instanssi asettaa JAR-tiedoston nimen ja kutsuu sitten sen sisällä() tapa tehdä kaikki todelliset työt:

 public JarResources (String jarFileName) {this.jarFileName = jarFileName; sen sisällä(); } 

Nyt sen sisällä() method lataa melkein vain määritetyn JAR-tiedoston koko sisällön hashtableen (pääsee resurssin nimen kautta).

Tämä on melko raskas menetelmä, joten hajotetaan se hieman pidemmälle. ZIP-tiedosto luokka antaa meille pääsyn JAR / zip-arkiston otsikkotietoihin. Tämä on samanlainen kuin tiedostojärjestelmän hakemistotiedot. Tässä luetellaan kaikki ZIP-tiedosto ja rakenna htKoot hashtable kunkin arkiston resurssin koon kanssa:

 private void init () {kokeile {ZipFile zf = uusi ZipFile (jarFileName); Luettelo e = zf.entries (); while (e.hasMoreElements ()) {ZipEntry ze = (ZipEntry) e.nextElement (); if (debugOn) {System.out.println (dumpZipEntry (ze)); } htSizes.put (ze.getName (), uusi kokonaisluku ((int) ze.getSize ())); } zf.close (); 

Seuraavaksi pääsemme arkistoon ZipInputStream luokassa. ZipInputStream luokka tekee kaiken taikuuden, jotta voimme lukea kaikki arkiston yksittäiset resurssit. Luemme tarkan tavujen määrän arkistosta, joka sisältää kunkin resurssin, ja tallennamme kyseisen datan htJarContents hashtable käytettävissä resurssin nimellä:

 FileInputStream fis = uusi FileInputStream (jarFileName); BufferedInputStream bis = uusi BufferedInputStream (fis); ZipInputStream zis = uusi ZipInputStream (bis); ZipEntry ze = nolla; while ((ze = zis.getNextEntry ())! = null) {if (ze.isDirectory ()) {jatka; } if (debugOn) {System.out.println ("ze.getName () =" + ze.getName () + "," + "getSize () =" + ze.getSize ()); } int koko = (int) ze.getSize (); // -1 tarkoittaa tuntematonta kokoa. if (koko == - 1) {koko = ((Kokonaisluku) htSizes.get (ze.getName ())). intValue (); } tavu [] b = uusi tavu [(int) koko]; int rb = 0; int kimpale = 0; kun taas (((int) koko - rb)> 0) {chunk = zis.read (b, rb, (int) size - rb); if (pala == - 1) {tauko; } rb + = palo; } // lisää sisäiseen resurssiin hashtable 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 ("valmis"); } catch (FileNotFoundException e) {e.printStackTrace (); } catch (IOException e) {e.printStackTrace (); }} 

Huomaa, että kunkin resurssin tunnistamiseen käytetty nimi on arkistossa olevan resurssin kelvollinen polun nimi, ei, esimerkiksi luokan nimi paketissa - eli ZipEntry java.util.zip-paketin luokan nimi olisi "java / util / zip / ZipEntry" eikä "java.util.zip.ZipEntry".

Viimeinen tärkeä osa koodia on yksinkertainen testiohjain. Testiajuri on yksinkertainen sovellus, joka vie JAR / zip-arkiston nimen ja resurssin nimen. Se yrittää löytää resurssin arkistosta ja raportoi sen onnistumisesta tai epäonnistumisesta:

 public static void main (String [] args) heittää IOExceptionin {if (args.pituus! = 2) {System.err.println ("käyttö: java JarResources"); System.exit (1); } JarResources jr = uudet JarResources (argumentit [0]); tavu [] buff = jr.getResource (argumentit [1]); if (buff == null) {System.out.println ("Ei löydy" + args [1] + "."); } else {System.out.println ("Löydetty" + args [1] + "(pituus =" + buff.length + ")."); }}} // JarResources-luokan loppu. 

Ja sinulla on se. Helppokäyttöinen luokka, joka kätkee kaiken sekavuuden, joka liittyy JAR-tiedostoihin piilotettujen resurssien käyttöön.

Harjoituksia lukijalle

Nyt kun olet halunnut purkaa resursseja arkistotiedostosta, tässä on joitain ohjeita, joita saatat haluta tutkia muokkaamalla ja laajentamalla JarResources luokka:

  • Sen sijaan, että lataat kaiken rakentamisen aikana, suorita viivästynyt lataus. Ison JAR-tiedoston tapauksessa muistia ei ehkä riitä kaikkien tiedostojen lataamiseen rakentamisen aikana.
  • Sen sijaan, että tarjottaisiin yksinkertaisesti yleinen käyttöoikeusmenetelmä, kuten getResource (), voisimme tarjota muita resurssikohtaisia ​​käyttöoikeuksia - esimerkiksi getImage (), joka palauttaa Java Kuva esine, getClass (), joka palauttaa Java Luokka objekti (räätälöidyn luokan lataajan avulla) ja niin edelleen. Jos JAR-tiedosto on tarpeeksi pieni, voimme rakentaa kaikki resurssit niiden laajennusten (.gif, .class ja niin edelleen) perusteella.
  • Joidenkin menetelmien pitäisi antaa tietoa itse annetusta JAR-tiedostosta (pohjimmiltaan kääre ympärille ZIP-tiedosto), mukaan lukien: Jar / zip-merkintöjen määrä; luetteloija, joka palauttaa kaikki resurssien nimet; lisenssit, jotka palauttavat tietyn merkinnän pituuden (ja muut määritteet); ja lisenssin, joka sallii indeksoinnin, muutamia mainitakseni.
  • JarResources voidaan laajentaa applettien käyttämään. Hyödyntämällä sovelmaparametreja ja URLConnection luokassa JAR-sisältö voidaan ladata verkosta sen sijaan, että arkistoa avattaisiin paikallisina tiedostoina. Lisäksi voimme laajentaa tätä luokkaa mukautettuna Java-sisällönkäsittelijänä.

Johtopäätös

Jos olet ollut innokas tietämään, kuinka kuva voidaan purkaa JAR-tiedostosta, sinulla on nyt tapa. Pystyt paitsi käsittelemään kuvia JAR-tiedostolla, myös tämän vihjeen uuden luokan avulla, voit työskennellä maagisesi kanssa minkä tahansa resurssi JAR: lta.

Arthur Choi työskentelee tällä hetkellä IBM: ssä neuvonantajana. Hän on työskennellyt useissa yrityksissä, kuten SamSung Network Laboratory ja MITER. Eri projektit, joissa hän on työskennellyt, ovat asiakas / palvelinjärjestelmät, hajautettu objektien laskenta ja verkon hallinta. Hän on käyttänyt useita kieliä eri käyttöjärjestelmäympäristöissä. Hän aloitti ohjelmoinnin vuonna 1981 FORTRAN IV: n ja COBOLin kanssa. Myöhemmin hän siirtyi käyttämään C: tä ja C ++: ta, ja hän on työskennellyt Javan kanssa noin kaksi vuotta. Häntä kiinnostaa eniten Java-sovellukset tietovarastojen alueilla laaja-alaisissa verkoissa sekä rinnakkainen ja hajautettu käsittely Internetin kautta (käyttäen agenttipohjaista ohjelmointia). John Mitchell, työntekijä, konsultti ja oman yrityksen johtaja, on investoinut viimeiset kymmenen vuotta huippuluokan tietokoneohjelmistojen kehittämiseen sekä muiden kehittäjien neuvontaan ja koulutukseen. Hän on konsultoinut Java-tekniikkaa, kääntäjiä, tulkkia, verkkopohjaisia ​​sovelluksia ja verkkokauppaa. John on kirjoittanut Making Sense of Java: A Guide for Managers and Rest of Us ja on julkaissut artikkeleita ohjelmointilehdissä. Sen lisäksi, että hän kirjoittaa Java Tips -sarakkeen JavaWorldille, hän valvoo comp.lang.tcl.announce- ja comp.binaries.geos-uutisryhmiä.

Lisätietoja tästä aiheesta

  • Tässä on luokkatiedosto JarResources.java //www.javaworld.com/javatips/javatip49/JarResources.java
  • JARit //www.javasoft.com/products/jdk/1.1/docs/guide/jar/index.html
  • Lisätietoja Java-arkistoinnin tuesta on ohjeaiheessa "Java Tip 21Käytä arkistotiedostoja appletien lataamisen nopeuttamiseksi" //www.javaworld.com/javatips/jw-javatip21.html

Tämän tarinan "Java Tip 49: Java-resurssien purkaminen JAR- ja zip-arkistoista" julkaisi alun perin JavaWorld.