Открыть ресурс с относительным путем в Java

В моем приложении Java мне нужно получить несколько файлов и каталогов.

Это структура программы:

./main.java
./package1/guiclass.java
./package1/resources/resourcesloader.java
./package1/resources/repository/modules/   -> this is the dir I need to get
./package1/resources/repository/SSL-Key/cert.jks    -> this is the file I need to get

guiclass загружает класс resourcesloader, который будет загружать мои ресурсы (каталог и файл).

Что касается файла, я пытался

resourcesloader.class.getClass().getResource("repository/SSL-Key/cert.jks").toString()

для того, чтобы получить реальный путь, но этот способ не работает.

Я понятия не имею, как сделать каталог.

13 ответов

Решение

Укажите путь относительно загрузчика классов, а не класса, из которого вы получаете загрузчик. Например:

resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString();

У меня были проблемы с использованием getClass().getResource("filename.txt") метод. После прочтения инструкций по Java-документации, если ваш ресурс не находится в том же пакете, что и класс, из которого вы пытаетесь получить доступ к ресурсу, вы должны указать ему относительный путь, начиная с '/', Рекомендуемая стратегия - поместить файлы ресурсов в папку "resources" в корневом каталоге. Так, например, если у вас есть структура:

src/main/com/mycompany/myapp

Затем вы можете добавить папку ресурсов в соответствии с рекомендациями maven в:

src/main/resources

кроме того, вы можете добавить подпапки в папке ресурсов

src/main/resources/textfiles

и сказать, что ваш файл называется myfile.txt так что у тебя есть

src/main/resources/textfiles/myfile.txt

Теперь вот где возникает проблема тупого пути. Скажем, у вас есть класс в вашем com.mycompany.myapp packageи вы хотите получить доступ к myfile.txt файл из папки вашего ресурса. Некоторые говорят, что вам нужно дать:

"/main/resources/textfiles/myfile.txt" path

или же

"/resources/textfiles/myfile.txt"

оба они не правы. После того как я побежал mvn clean compile, файлы и папки копируются в:

myapp/target/classes 

папка. Но папки ресурсов нет, просто папки в папке ресурсов. Так что у тебя есть:

myapp/target/classes/textfiles/myfile.txt

myapp/target/classes/com/mycompany/myapp/*

поэтому правильный путь, чтобы дать getClass().getResource("") метод это:

"/textfiles/myfile.txt"

вот:

getClass().getResource("/textfiles/myfile.txt")

Это больше не будет возвращать ноль, но вернет ваш класс. Надеюсь, это кому-нибудь поможет. Мне странно, что "resources" папка тоже не копируется, а только подпапки и файлы прямо в "resources" папка. Мне показалось бы логичным, что "resources" папка также находится в "myapp/target/classes"

В надежде предоставить дополнительную информацию для тех, кто не подхватывает эту информацию так же быстро, как другие, я хотел бы представить свой сценарий, так как он имеет немного другую настройку. Мой проект был настроен со следующей структурой каталогов (с использованием Eclipse):

Проект /
  src / // исходный код приложения
    орг /
      мой проект/
        MyClass.java
  test/               // модульные тесты
  res / // ресурсы
    images/           // PNG картинки для иконок
      мой-image.png
    xml/              // XSD-файлы для проверки XML-файлов с помощью JAXB
      мой-schema.xsd
    conf/             // файл по умолчанию.conf для Log4j
      log4j.conf
  lib/                // библиотеки добавлены в build-path через настройки проекта

У меня были проблемы с загрузкой моих ресурсов из каталога res. Я хотел, чтобы все мои ресурсы были отделены от моего исходного кода (просто для целей управления / организации). Итак, мне нужно было добавить каталог res в путь сборки, а затем получить доступ к ресурсу через:

static final ClassLoader loader = MyClass.class.getClassLoader();

// in some function
loader.getResource("images/my-image.png");
loader.getResource("xml/my-schema.xsd");
loader.getResource("conf/log4j.conf");

ПРИМЕЧАНИЕ: / отсутствует в начале строки ресурса, потому что я использую ClassLoader.getResource(String) вместо Class.getResource (String).

@GianCarlo: Вы можете попробовать вызвать системное свойство user.dir, которое даст вам корень вашего Java-проекта, а затем добавить этот путь к вашему относительному пути, например:

String root = System.getProperty("user.dir");
String filepath = "/path/to/yourfile.txt"; // in case of Windows: "\\path \\to\\yourfile.txt
String abspath = root+filepath;



// using above path read your file into byte []
File file = new File(abspath);
FileInputStream fis = new FileInputStream(file);
byte []filebytes = new byte[(int)file.length()];
fis.read(filebytes);

Когда вы используете 'getResource' для класса, относительный путь разрешается на основе пакета, в котором находится класс. Когда вы используете 'getResource' для ClassLoader, относительный путь разрешается на основе корневой папки.

Если вы используете абсолютный путь, оба метода getResource будут запускаться в корневой папке.

Для тех, кто использует eclipse + maven. Скажем, вы пытаетесь получить доступ к файлу images/pic.jpg в src/main/resources, Делать это так:

ClassLoader loader = MyClass.class.getClassLoader();
File file = new File(loader.getResource("images/pic.jpg").getFile());

совершенно правильно, но может привести к исключению нулевого указателя. Похоже, eclipse не распознает папки в структуре каталогов maven сразу как исходные. Удаляя и src/main/resources папку из списка исходных папок проекта и положить его обратно (проект> свойства> путь сборки Java> источник> удалить / добавить папку), я смог решить эту проблему.

Чтобы получить реальный путь к файлу, вы можете попробовать следующее:

URL fileUrl = Resourceloader.class.getResource("resources/repository/SSL-Key/cert.jks");
String pathToClass = fileUrl.getPath;    

Resourceloader - это имя класса здесь. "resources/repository/SSL-Key/cert.jks" - относительный путь к файлу. Если бы у вас был guiclass в./package1/java с остальной структурой папок, вы бы выбрали "../resources/repository/SSL-Key/cert.jks" как относительный путь из-за правил, определяющих относительный путь.

Таким образом, вы можете читать свой файл с помощью BufferedReader. НЕ ИСПОЛЬЗУЙТЕ СТРОКУ для определения пути к файлу, потому что, если в вашем пути есть пробелы или символы неанглийского алфавита, у вас возникнут проблемы, и файл не будет найден.

BufferedReader bufferedReader = new BufferedReader(
                        new InputStreamReader(fileUrl.openStream()));
resourcesloader.class.getClass()

Можно разбить на:

Class<resourcesloader> clazz = resourceloader.class;
Class<Class> classClass = clazz.getClass();

Это означает, что вы пытаетесь загрузить ресурс, используя класс начальной загрузки.

Вместо этого вы, вероятно, хотите что-то вроде:

resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString()

Если бы только javac предупреждал о вызове статических методов в нестатических контекстах...

Следующие работы?

resourcesloader.class.getClass().getResource("/package1/resources/repository/SSL-Key/cert.jks")

Есть ли причина, по которой вы не можете указать полный путь, включая пакет?

Идем с двумя ответами, как указано выше. Первый

resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString();
resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString()

Должно быть одно и то же?

Использовать этот:

resourcesloader.class.getClassLoader().getResource("/path/to/file").**getPath();**

Я сделал небольшую модификацию на одном вкладыше @jonathan.cone (добавив .getFile()), чтобы исключить исключение нулевого указателя и установить путь к каталогу данных. Вот что сработало для меня:

String realmID = new java.util.Scanner(new java.io.File(RandomDataGenerator.class.getClassLoader().getResource("data/aa-qa-id.csv").getFile().toString())).next();

Один из стабильных способов работы во всех ОС - это использовать System.getProperty("user.dir")

      String filePath = System.getProperty("user.dir") + "/path/to/file.extension";

Path path = Paths.get(filePath);
if (Files.exists(path)) {
    return true;
}
Другие вопросы по тегам