Java съвет 49: Как да извлечете Java ресурси от JAR и zip архиви

Повечето програмисти на Java са доста ясни за предимствата на използването на JAR файл за обединяване на всички различни ресурси (т.е. .class файлове, звуци и изображения), които съставляват тяхното Java решение. (Ако не сте запознати с JAR файловете, вижте раздела „Ресурси“ по-долу.) Много често задаван въпрос от хора, които тепърва започват да включват JAR файлове в торбата си с трикове, е „Как да извлека изображение от JAR? " Ще отговорим на този въпрос и ще предоставим клас, който да улесни извличането на всеки ресурс от JAR!

Зареждане на GIF изображение

Да приемем, че имаме JAR файл, съдържащ куп .gif файлове с изображения, които искаме да използваме в нашето приложение. Ето как бихме могли да получим достъп до файл с изображение от JAR с помощта на JarResources:

JarResources jar = нов JarResources ("Images.jar"); Лого на изображението = Toolkit.getDefaultToolkit (). CreateImage (jar.getResource ("logo.gif");

Този кодов фрагмент показва, че можем да създадем JarResourcesобект, инициализиран в JAR файла, съдържащ ресурса, който се интересуваме от използването - Images.jar. След това използваме JarResources'getResource()метода, за да предоставим суровите данни от файла logo.gif за метода на инструментариума AWT createImage().

Бележка за именуването

JarResource е сравнително ясен пример за това как да се използват различни съоръжения, предоставени от Java 1.1, за манипулиране на JAR и zip архивни файлове.

Бърза бележка за именуването. Поддръжката за архивиране в Java всъщност започна с помощта на популярния формат за архивиране на zip (вижте „Java Съвет 21: Използвайте архивни файлове, за да ускорите зареждането на аплета“). И така, първоначално при внедряването на поддръжка на Java за манипулиране на архивните файлове всички класове и какво ли още не бяха поставени в пакета java.util.zip; тези класове обикновено започват с " Zip." Но някъде при преминаването към Java 1.1, правомощията, които трябва да бъдат променени, името на архива да бъде по-фокусирано върху Java. Следователно това, което сега наричаме JAR файлове, всъщност са zip файлове.

Как работи

Важните полета с данни за JarResourcesкласа се използват за проследяване и съхраняване на съдържанието на посочения JAR файл:

публичен финален клас JarResources {public boolean debugOn = false; private Hashtable htSizes = new Hashtable (); private Hashtable htJarContents = new Hashtable (); частен низ jarFileName;

И така, инстанцирането на класа задава името на JAR файла и след това извиква init()метода, за да извърши цялата реална работа:

public JarResources (String jarFileName) {this.jarFileName = jarFileName; в него(); }

Сега init()методът почти се зарежда в цялото съдържание на посочения JAR файл в хеш-таблица (достъпна чрез името на ресурса).

Това е доста солиден метод, така че нека го разделим още малко. В ZipFileкласа ни дава достъп до основната буркана / компресиран архив информацията в заглавието. Това е подобно на информацията в директорията във файлова система. Тук изброяваме всички записи в ZipFileи изграждаме хеш-таблицата htSizes с размера на всеки ресурс в архива:

private void init () {try {ZipFile zf = new ZipFile (jarFileName); Изброяване e = zf.entries (); докато (e.hasMoreElements ()) {ZipEntry ze = (ZipEntry) e.nextElement (); if (debugOn) {System.out.println (dumpZipEntry (ze)); } htSizes.put (ze.getName (), ново цяло число ((int) ze.getSize ())); } zf.close ();

След това получаваме достъп до архива чрез използването на ZipInputStreamкласа. Най- ZipInputStreamкласа прави всичко магията да ни позволи да се чете всеки от отделните ресурси в архива. Четем точния брой байтове от архива, който включва всеки ресурс, и съхраняваме тези данни в хеш-таблицата htJarContents, достъпна по име на ресурс:

FileInputStream fis = нов FileInputStream (jarFileName); BufferedInputStream bis = нов BufferedInputStream (fis); ZipInputStream zis = нов ZipInputStream (бис); ZipEntry ze = null; докато ((ze = zis.getNextEntry ())! = null) {if (ze.isDirectory ()) {продължение; } if (debugOn) {System.out.println ("ze.getName () =" + ze.getName () + "," + "getSize () =" + ze.getSize ()); } int размер = (int) ze.getSize (); // -1 означава неизвестен размер. if (size == - 1) {size = ((Integer) htSizes.get (ze.getName ())). intValue (); } байт [] b = нов байт [(int) размер]; int rb = 0; int парче = 0; while ((((int) size - rb)> 0) {chunk = zis.read (b, rb, (int) size - rb); ако (парче == - 1) {почивка; } rb + = парче; } // добавяне към хеш-таблица на вътрешния ресурс 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 ("готово."); } catch (FileNotFoundException e) {e.printStackTrace (); } catch (IOException e) {e.printStackTrace (); }}

Имайте предвид, че името, използвано за идентифициране на всеки ресурс, е името на квалифицирания път на ресурса в архива, а не , например, името на клас в пакет - тоест ZipEntryкласът от пакета java.util.zip би да бъде наречен "java / util / zip / ZipEntry", а не "java.util.zip.ZipEntry."

Последната важна част от кода е простият тестов драйвер. Тестовият драйвер е просто приложение, което взема JAR / zip архивно име и името на ресурс. Той се опитва да намери ресурса в архива и съобщава за неговия успех или неуспех:

public static void main (String [] args) хвърля IOException {if (args.length! = 2) {System.err.println ("употреба: java JarResources"); System.exit (1); } JarResources jr = нови JarResources (аргументи [0]); байт [] buff = jr.getResource (аргументи [1]); if (buff == null) {System.out.println ("Не можах да намеря" + аргументи [1] + "."); } else {System.out.println ("Намерен" + аргументи [1] + "(дължина =" + buff.length + ")."); }}} // Край на класа JarResources.

И ето го. Лесен за използване клас, който скрива всички обърквания, свързани с използването на ресурси, скрити в JAR файлове.

Упражнения за читателя

Сега, когато имате усещане за извличане на ресурси от архивен файл, ето няколко насоки, които може да искате да проучите при модифициране и разширяване на JarResourcesкласа:

  • Вместо да зареждате всичко по време на строителството, направете забавено зареждане. В случай на голям JAR файл, може да няма достатъчно памет за зареждане на всички файлове по време на изграждането.
  • Вместо просто да предоставим общ метод за достъп като getResource(), ние бихме могли да предоставим други специфични за ресурсите достъп - например, getImage()който връща Java Imageобект getClass(), който връща Java Classобект (с помощ от персонализиран load loader) и т.н. Ако JAR файлът е достатъчно малък, бихме могли предварително да изградим всички ресурси въз основа на техните разширения (.gif, .class и т.н.).
  • Някои методи трябва да предоставят информация за самия JAR файл (основно обвивка ZipFile), включително: броя на Jar / zip записите; изброител, който връща всички имена на ресурси; аксесоари, които връщат дължината (и други атрибути) на определен запис; и аксесоар, който позволява индексиране, за да назовем само няколко.
  • JarResourcesможе да се разшири, за да се използва от аплети. Чрез използване на параметрите на аплета и URLConnectionкласа, JAR съдържанието може да бъде изтеглено от мрежата, вместо да се отварят архивите като локални файлове. Освен това можем да разширим този клас като персонализиран обработчик на съдържание на Java.

Заключение

Ако сте били нетърпеливи да знаете как да извлечете изображение от JAR файл, сега имате начин. Не само можете да обработвате изображения с JAR файл, но и с новия клас, предоставен в този съвет, работите с извличането на магия на всеки ресурс от JAR.

В момента Артър Чой работи за IBM като консултант програмист. Работил е в няколко компании, включително SamSung Network Laboratory и MITER. Различните проекти, по които е работил, са клиент / сървърни системи, разпределени обектни изчисления и мрежово управление. Той е използвал редица езици в различни среди на операционната система. Започва да програмира през 1981 г. с FORTRAN IV и COBOL. По-късно той премина към C и C ++ и работи с Java от около две години. Той се интересува най-много от приложения на Java в областите на хранилища за данни чрез широкообхватни мрежи и паралелна и разпределена обработка чрез Интернет (с помощта на програмиране, базирано на агенти). Джон Мичъл, служител, консултант и директор на собствената си компания, инвестира последните десет години в разработването на авангарден компютърен софтуер,и при консултиране и обучение на други разработчици. Предоставя консултации по Java технология, компилатори, преводачи, уеб-базирани приложения и интернет търговия. Джон е съавтор на „Осмисляне на Java: Ръководство за мениджърите и останалите от нас“ и публикува статии в списания за програмиране. В допълнение към писането на колоната Java Tips за JavaWorld, той модерира групите за новини comp.lang.tcl.announce и comp.binaries.geos.

Научете повече за тази тема

  • Ето файла на класа JarResources.java//www.javaworld.com/javatips/javatip49/JarResources.java
  • JARs //www.javasoft.com/products/jdk/1.1/docs/guide/jar/index.html
  • За повече информация относно поддръжката за архивиране в Java, вижте „Съвет на Java 21 Използвайте архивни файлове, за да ускорите зареждането на аплета“ //www.javaworld.com/javatips/jw-javatip21.html

Тази история, "Java Съвет 49: Как да извлечете Java ресурси от JAR и zip архиви" първоначално е публикувана от JavaWorld.