2009-02-12 7 views
2

Я расширяю класс утилиты, объединяющий набор образов и файлы описания .xml. В настоящее время я храню все файлы в каталоге и загружаю их оттуда. Каталог выглядит следующим образом:Извлечение файлов из Jar более эффективно

8.png 
8.xml 
9.png 
9.xml 
10.png 
10.xml 
... 
... 
50.png 
50.xml 
... 



Вот мой текущий конструктор. Он молниеносно и делает то, что мне нужно. (Я раздел некоторые проверки ошибок, чтобы сделать его более удобным для чтения):

public DivineFont(String directory) { 

    File dir = new File(directory); 

    //children is an array that looks like this: '10.fnt', '11.fnt', etc. 
    String[] children = dir.list(fntFileFilter); 

    fonts = new Hashtable<Integer, AngelCodeFont>(100); 

    AngelCodeFont buffer; 
    int number; 
      String fntFile; 
      String imgFile; 

    for(int k = 0; k < children.length; k++) { 
     number = Integer.parseInt(children[k].split("\\.")[0]); 
     fntFile = directory + File.separator + number + ".xml"; 
     imgFile = directory + File.separator + number + ".png"; 
     buffer = new AngelCodeFont(fntFile, imgFile); 

     fonts.put(number, buffer); 
    } 
} 

Ради WebStart и чистоты, я пытался загрузить эти ресурсы из Jar вместо , У меня это работает, но время загрузки от мгновенного до нескольких секунд, и это неприемлемо. Вот код, который я попробовал (опять же, проверка ошибок раздели):.

(Это не лучший способ сделать то, что я хочу сделать, это макет, чтобы увидеть, если идея сработала Это Ждут» . Тл два для петель никоим образом не является источником проблемы, это процесс создания всех этих InputStreams, что замедляет его)

public DivineFont(String jarFileName) { 

    JarFile jarfile = new JarFile(jarFileName); 
    Enumeration<JarEntry> em = jarfile.entries(); 
    ArrayList<Integer> fontHeights = new ArrayList<Integer>(100); 
    for (Enumeration em1 = jarfile.entries(); em1.hasMoreElements();) { 
     String fileName = em1.nextElement().toString(); 
     if(fileName.endsWith(".fnt")) { 
      fontHeights.add(Integer.parseInt(fileName.split("\\.")[0])); 
     } 
    } 

    fonts = new Hashtable<Integer, AngelCodeFont>(100); 

    AngelCodeFont buffer; 
    int number; 

    for(int k = 0; k < fontHeights.size(); k++) { 
     number = fontHeights.get(k); 
     InputStream fntFileStream = jarfile.getInputStream(jarfile.getEntry(number + ".xml")); 
     InputStream pngFileStream = jarfile.getInputStream(jarfile.getEntry(number + ".png")); 
     buffer = new AngelCodeFont(String.valueOf(number), fntFileStream, pngFileStream); 

     fonts.put(number, buffer); 


    } 
} 


Каждый знает лучший способ работать с .jar-файлами, кроме того, как я здесь пробовал? Вот AngelCodeFont API. Если бы это было абсолютно необходимо, я мог бы написать патч для этого, но мне бы этого не хотелось. Мне кажется, что, вероятно, есть способ сделать то, что я хочу сделать, я просто не знаком с этим.

Я не ужасно против того, чтобы быстро сбросить банку во временный каталог, а затем прочитать файлы оттуда, но если есть способ сделать это, читая прямо из банки, я бы скорее сделал это.

Также: компрессия не является проблемой вообще. Единственная причина, по которой я использую банку, - это проблема упаковки.

ответ

1

Ну, я нашел ответ. Ответ на мой первоначальный вопрос был «Неверный вопрос». Файл Jar не был проблемой, это была библиотека, которую я использовал для загрузки изображений.

Когда я загружался из файловой системы, изображение называлось «38.png» и т. Д. Когда я загружался из Jar, я просто называет его «38».

Класс загрузчика изображений внутри библиотеки использует расширение файла имени, чтобы определить, какой загрузчик изображений использовать. Если расширение файла отсутствует, в нем используется более медленный базовый загрузчик изображений. Когда я изменил эту строку:

buffer = new AngelCodeFont(String.valueOf(number), fntFileStream, pngFileStream); 

этой линии:

buffer = new AngelCodeFont(number + ".png", fntFileStream, pngFileStream); 

Мы сами победителем.

Спасибо за помощь в любом случае, ребята. Мне потребовалось несколько часов, чтобы понять это, но если бы не ваши сообщения, я, вероятно, продолжал бы считать, что виноват скорее Java, чем библиотека, которую я использую.

-2

This library не может сжать столько, сколько вам нужно, но это будет быстрее ...

+0

Сжатие не является проблемой. Простота использования для Webstart. Вот почему я хочу положить его в банку. Спасибо хоть. :-) – JoshuaD

4

Открытие баночка очень дорогая операция. Таким образом, вы можете сначала открыть JAR и сохранить экземпляр JarFile в статическом поле где-нибудь. В вашем случае вы также захотите прочитать все записи и сохранить их в hashmap для мгновенного доступа к ресурсу, в котором вы нуждаетесь.

Другим решения является поставить JAR на пути к классам и использовать

DivineFont.class.getContextClassLoader().getResource*("/8.png"); 

вида "/"! Если вы его опустите, Java будет искать в том же каталоге (пакете), в котором он находит файл DivineFont.class.

Получение вещей из classpath было оптимизировано до смерти на Java.

+0

Это возвращает только URL-адрес, который не приносит мне никакой пользы. Конструкторы AngelCodeFont не поддерживают URL-адреса, и в любом случае, если бы это было так, все равно было бы создавать два новых InputStreamReaders каждый раз, когда вызывался конструктор. – JoshuaD

+0

Затем используйте getResourceAsStream(). –

+0

InputStreamReaders дешевы; то, что убивает вас, - это линия с новым JarFile(). –

0

манипуляции Jar-файл может быть очень дорогим, и библиотека классов Java уже реализует этот вид загрузки ресурсов (вероятно, как можно более эффективно.)

Плюс, как только вы в WebStart, ваши имена файлов JAR будет получить искалечены, так что вам, скорее всего, придется изучить каждый файл jar на пути к классу, чтобы загрузить ваши ресурсы (я сделал это! Уродливый!)

Вместо этого используйте Class.getResourceAsStream(String resourceName). Я не профилировал его, но я не заметил, что он заметно медленнее, чем прямой доступ к файлам.

+0

Спасибо, Джаред. Сейчас я на работе, но сегодня я попробую. Я дам вам знать, как это происходит. – JoshuaD