Загрузка файлов с помощью ClassLoader

Эта проблема давно искала меня. Мне нужно загрузить пару файлов в моем приложении java, и единственный способ, которым я работал, выглядит так:

URL hsURL;
if(System.getProperty("os.name").toLowerCase().contains("windows")) {
    hsURL = new URL("file:/" + System.getProperty("user.dir") + "/helpsets/helpset.hs");
}
else {
    hsURL = new URL("file://" + System.getProperty("user.dir") + "/helpsets/helpset.hs");
}

Но это уродливо и ужасно. Некоторое время я думал, что это работает:

hsURL = ClassLoader.getSystemResource("helpsets/helpset.hs");

Но это уже не работает по какой-то причине (я, должно быть, что-то изменил и не заметил. Он возвращает null.

Должен ли я использовать getResource() вместо getSystemResource() (если это так, почему getSystemResource() статический, но не getResource())?

Я использую eclipse, и я попытался включить папку в путь сборки (classpath), и не включая ее, это, похоже, не имеет значения.

Ответ 1

getSystemResource является статическим, потому что он будет использовать системный загрузчик классов, который доступен статически. (ClassLoader.getSystemClassLoader)

Если ваш ресурс доступен в пути к классам, я бы предложил использовать ClassLoader.getResource() или Class.getResource из соответствующего класса, например.

Foo.class.getResource("/helpsets/helpset.hs");

(ClassLoader.getResource является "абсолютным"; Class.getResource относится к пакету класса, если вы не префикс его с помощью '/'.)

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

EDIT: я обычно считаю URL менее полезным, чем InputStream, поэтому я использую getResourceAsStream вместо getResource. YMMV

Ответ 2

Вы упомянули здесь несколько разных вещей, поэтому отпустите их.

1) Создание URL-адреса "file:" на основе "user.dir"

Свойство user.dir относится к текущему рабочему каталогу - где бы пользователь ни находился, когда он начал приложение. Скорее всего, файлы, написанные здесь, будут исчезать между двумя прогонами (потому что пользователь может запускаться из другого каталога).

Свойство "user.home" относится к домашнему каталогу пользователя, который должен оставаться неизменным между прогонами.

В любом случае, используйте объект File для открытия файлов, не обманывайте себя при создании URL-адреса "file:". Вы не получаете никакой пользы, и, как вы можете видеть, вам нужно написать беспорядочный код для доступа к нему.

2) Получение ресурса через загрузчик классов

Это предназначено для извлечения файлов, которые упакованы вместе с вашим приложением - файлы только для чтения. Как вы видели, существует несколько вариантов. Я предпочитаю использовать следующее, потому что я предполагаю, что класс захочет загрузить файл, который упакован вместе с ним.

InputStream in = this.getClass().getClassLoader().getResourceAsStream(fileName);