понедельник, 7 ноября 2011 г.

Проблемы новичков

Есть вещи, видимо настолько очевидные для опытных разработчиков, что они о таком никогда не пишут, считая что уж ЭТО настолько очевидно, что и разжевывать тут нечего. А новички сталкиваются с совершенно тупыми проблемами и не могут найти как же эту проблему решать.

 

Одна из таких проблем - работа с ресурсами. На Си меня совершенно не волновало куда положить всякие картинки, звуки и как их потом оттуда взять. Создал папку, накидал как хотел, если много - привел в порядок и поехали. На Java я первоначально именно так и поступил, но потом пришлось чесать репу:

чтобы сделать из приложения апплет, или сделать возможным Web Start - ресурсы должны хранится в jar. Т.е. можно конечно обойтись и без этого, даже в таких случаях, но некошерными методами. Главное засунуть их туда проблемы нет вообще - jar, это тот же zip, и положить что-то внутрь можно даже силами файлового менеджера, многие из них давно умеют обращаться с такими файлами как собычными папками. Но как потом из программы обратится к положенному?

Оказалось все достаточно тривиально (однако чувствуются некоторые подводные камни и спрятанные грабли). Итак, руководство для новичков, как обращаться с ресурсами в Java:

предполагается что вы пользуетесь Eclipse, в прочих IDE не должно сильно отличаться. 

  • создаем новый package: File->New->Package и даем ему какое-то разумное имя. Например resources. Или images
  • ложим туда все наши картинки. Если вы уже сделали простую папку и натолкали их туда - перетаскиваем мышой, если они лежат где-то отдельно, не подключенные к проекту - можно сделать импорт.
  • InputStream is=getClass().getResourceAsStream("/images/example.png") - получаем InputStream для файла example.png лежащего в пакете images
  • Вуаля! 

Если вы привыкли работать с File - отвыкайте. В общем-то он нужен вам чтобы получить все тот же InputStream. Если какие-то методы требуют File, то поищите - и обнаружите что они имеют вариант с InputStream.

Если вы сделали пакет resources.images, то обращение к файлу будет выглядеть так: 

InputStream is=getClass().getResourceAsStream("/resources/images/example.png");

Все точки в названии пакета заменяются на / и не забывайте про ведущий слэш.

Если обнаружите что можно сделать так

InputStream is=getClass().getResource("/resources/images/example.png").getFile();

то вдумчиво читайте описание всех упомянутых методов, ничего хорошего у вас так не выйдет :). 

Когда придет время явить свое творение миру, вы сформируете единый jar со всем что нужно для счастья при помощи maven, или ручками. Если второй вариант, то не забывайте: во время отладки эклипса сама формирует переменные типа classpath и прочую фигню так чтобы ваша программа видела свои ресурсы - но в bin, как откомпилированные классы, их не копирует. Так что когда будете делать jar, кроме классов не забывайте затолкать лежащие отдельно ресурсы - не нарушая структуры packages.

Т.е. если у вас класс yourpackage.YourApp и ресурс resources.images.example.png, то структура jar-файла:

  • yourpackage
    • YourApp.java
  • resources
    • images
      • example.png

Про нативные либы песня отдельная. Их ложат в отдельный jar, прямо в корень и подключают к апплету или web start application путем указания соответствующего элемента в jnlp файле.

Если вы не собираетесь делать апплет или webstart - просто положите в отдельную папку и в скрипте запуска вашего приложения укажите путь:

 

#!/bin/sh

java -Djava.library.path=lib -jar myapp-1.0.0-jar-with-dependencies.jar

 

в папке где у меня лежит приложение в виде одного jar со всеми прибамбасами и ресурсами myapp-1.0.0-jar-with-dependencies.jar есть еще папочка lib, где валяются нативные либы. Можно сделать несколько папочек, но тогда придется указывать их все через ":".

Комментариев нет:

Отправить комментарий