Открыть ресурс с относительным путем в 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;
}