Каким способом лучше указывать путь к файлу в программе на языке Java? Где лучше хранить используемые программой файлы?
Насколько я понимаю, так делать совсем плохо, ибо мы не знаем, куда пользователь сохранит нашу программу. Можно прописать относительный путь к файлу, скажем вот так:
Image img = new ImageIcon("img.png").getImage();
Но тогда (если только я правильно понял из проделанных экспериментов) чтобы получить полный путь к файлу JVM делает «конкатенацию» текущей директории с прописанным относительным путём. Т.е. если я запускаю программу такой командой:
G:\program\bin>java -jar Program.jar
То JVM будет искать файл по такому расположению:
G:\program\bin\img.png
Насколько я понимаю, так делать совсем плохо, ибо мы не знаем, с какой директории будет запускать пользователь нашу программу. Можно делать что-то вообще интересное и непростое, типа такого:
Image img = new ImageIcon( this.getClass().getResource("img.png") ).getImage();
Здесь поиск файла будет происходить из пакета, где находится класс this.getClass() . (т.е. та самая «конкатенация» происходит с путём к пакету класса) Но ведь наверное плохо мешать файлы классов с файлами ресурсов? Или даже так:
Image img = new ImageIcon( this.getClass().getResource("/img.png") ).getImage();
Здесь поиск файла происходит в директориях classpath . Но по идее, тогда может оказаться несколько подходящих файлов? И что же это будет?! В общем вопросы: Правильно ли то, что я написал? Какие ещё способы существуют? Когда какой способ использовать? Какой способ наилучший (если он существует)?
Отслеживать
задан 24 фев 2016 в 17:13
743 1 1 золотой знак 9 9 серебряных знаков 24 24 бронзовых знака
intellij idea лучше всего так Run -> Edit configuration -> working derictory(указать рабочую директорию)
24 фев 2016 в 17:48
Хранить изображения и другие ресурсы не нуждающиеся в редактировании внутри JAR — нормальная практика. Обычно создают отдельный каталог images на одном уровне с корнем пакета, либо копируют его туда при сборке JAR.
24 фев 2016 в 17:48
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Общим ответом на это будет просто слово «зависит» — главный вопрос в том, с чем вы работаете. Как правило, java-приложения распространяются в виде jar-архивов, и если у вас есть распространяемые с приложением ресурсы (например, иконки), то они должны либо оказаться именно там, среди классов, либо, если вы распространяете приложение в виде архива и отдельных ресурсов снаружи архива, то вам нужно самому находить расположение jar-файла и вручную восстанавливать путь к ресурсом по аналогии с working directory. В случае, если вы пишете некоторую утилиту, которая обрабатывает аргументы, то вам, скорее всего, придется иметь дело из абсолютными, и с относительными путями — если вы пишете, скажем, ресайзер изображений, то вызов java -jar path/resizer.jar image.png 300×400 потребует простого проброса аргумента внутрь ImageIcon напрямую, без вообще какого-либо анализа.
Другими словами, все описанные методы имеют свое применение, и являются более или менее предпочтительными в зависимости от ситуации; каждый из них не чем-то плох, а неприменим в текущей ситуации. Если вопрос заключается в поиске ресурсов приложения, то лучше всего либо закидывать в jar, либо искать место установки приложения и отсчитывать от него (т.к. working dir может оказатсья любым).
Отслеживать
ответ дан 24 фев 2016 в 18:10
36.1k 2 2 золотых знака 55 55 серебряных знаков 82 82 бронзовых знака
Т.е. в jar-архиве создаётся отдельная папка, в которую заносятся файлы ресурсов, а обращение к ним происходит с помощью 4-ого способа, да?
Знакомство с файлами
Если вы хотите написать программу, которая делает что-то с файлами на диске, это у вас очень легко получится. В Java очень много классов, которые помогают вам работать как с самими файлами, так и с их содержимым.
В ранних версиях Java для работы с файлами использовались классы типа File и FileInputStream . Но теперь класс File считается устаревшим, и использовать его не рекомендуется. Вы, конечно, можете еще встретить его в коде, параметрах методов или конструкторах классов.
Мы будем начинать изучение работы с файлами сразу с класса Path . Path — это класс, который пришел на смену File . Работа с ним безопаснее и эффективнее.
Класс Path
Технически Path — это не класс, а интерфейс. Так сделано для того, чтобы можно было под каждую операционную (и файловую) систему писать свой класс-наследник Path .
У Windows свои стандарты написания пути файлов, у Linux — свои. А ведь в мире еще много операционных систем, и у каждой — свои стандарты.
Поэтому везде в методах для работы с файлами указан интерфейс Path , а реально работа идет с его классами-наследниками: WindowsPath , UnixPath , .
Создание объекта Path
Чтобы создать объект Path (на самом деле это будет объект класса-наследника — WindowsPath ), нужно воспользоваться командой вида:
Path имя = Path.of(путь);
Где имя — это имя переменной типа Path . путь — это путь к файлу (или директории) вместе с именем файла (или директории). А of — статический метод класса Path .
Метод of() используется для того, чтобы создать объекты типа WindowsPath если программа запускается под Windows, а если программа запускается под Linux — объекты UnixPath . Вы не можете создать объект типа Path с помощью кода вида new Path() .
Path file = Path.of("c:\\projects\\note.txt");
Path directory = Path.of("c:\\projects\\");
Файл (или директория) не обязаны существовать, чтобы мог существовать валидный объект типа Path . Может вы только хотите создать файл. Объект типа Path — это как продвинутая версия типа String — он не привязан к конкретному файлу на диске: он просто хранит некий путь на диске и все.
2. Методы типа Path
У интерфейса Path есть довольно много интересных методов. Самые интересные представлены в таблице ниже.
Path getParent()
Path getFileName()
Path getRoot()
boolean isAbsolute()
Path toAbsolutePath()
Path normalize()
Path resolve(Path other)
Path relativize(Path other)
boolean startsWith(Path other)
boolean endsWith(Path other)
int getNameCount()
Path getName(int index)
Path subpath(int beginIndex, int endIndex)
File toFile()
URI toUri()
Ниже идет краткое описание существующих методов.
3. Разделение пути на части
Метод getParent() возвращает путь, который указывает на родительскую директорию для текущего пути. Независимо от того, был этот путь директорией или файлом:
String str = "c:\\windows\\projects\\note.txt"; Path path = Path.of(str).getParent();
"c:\\windows\\projects\\"
String str = "c:\\windows\\projects\\"; Path path = Path.of(str).getParent();
"c:\\windows\\"
String str = "c:\\"; Path path = Path.of(str).getParent();
null
Метод getFileName() возвращает одно имя файла (или директории) — то, что идет после последнего разделителя:
String str = "c:\\windows\\projects\\note.txt"; Path path = Path.of(str).getFileName();
"note.txt"
String str = "c:\\windows\\projects\\"; Path path = Path.of(str).getFileName();
"projects"
String str = "c:\\"; Path path = Path.of(str).getFileName();
null
Метод getRoot() возвращает путь к корневой директории:
String str = "c:\\windows\\projects\\"; Path path = Path.of(str).getRoot();
4. Абсолютный и относительный пути
Пути бывают двух типов: абсолютные и относительные. Абсолютный путь начинается с корневой директории. Для Windows это может быть папка c:\ , для Linux — директория /
Относительный путь считается относительно какой-то директории. Т.е. это как бы конец пути, но только без начала. Относительный путь можно превратить в абсолютный и наоборот
Метод boolean isAbsolute()
Метод проверяет, является ли текущий путь абсолютным
String str = "c:\\windows\\projects\\note.txt"; boolean abs = Path.of(str).isAbsolute();
true
String str = "src\\com\\javarush\\Main.java"; boolean abs = Path.of(str).isAbsolute();
false
Метод Path toAbsolutePath()
Превращает путь в абсолютный, если нужно — добавляет к нему текущую рабочую директорию:
String str = "c:\\windows\\projects\\note.txt"; Path path = Path.of(str).toAbsolutePath();
"c:\\windows\\projects\\note.txt"
String str = "src\\com\\javarush\\Main.java"; Path path = Path.of(str).toAbsolutePath();
"d:\\work\\src\\com\\javarush\\Main.java"
Метод Path normalize()
В пути вместо имени директории можно писать «..», и это будет означать вернуться на одну директорию назад. Нормализация устраняет эти вещи. Примеры:
String str = "c:\\windows\\..\\projects\\note.txt"; Path path = Path.of(str).normalize();
"c:\\projects\\note.txt"
String str = "src\\com\\javarush\\..\\Main.java"; Path path = Path.of(str).normalize();
"src\\com\\Main.java"
Метод Path relativize(Path other)
Метод relativize() позволяет вычислить «разницу путей»: один путь относительно другого
Path path1 = Path.of("c:\\windows\\projects\\note.txt"); Path path2 = Path.of("c:\\windows\\"); Path result = path2.relativize(path1);
"projects\\note.txt"
Path path1 = Path.of("c:\\windows\\projects\\note.txt"); Path path2 = Path.of("c:\\windows\\"); Path result = path1.relativize(path2);
Path path1 = Path.of("c:\\aaa\\bbb\\1.txt"); Path path2 = Path.of("d:\\zzz\\y.jpg"); Path result = path1.relativize(path2);
Ошибка IllegalArgumentException: два пути имеют разный "корень" (разные диски)
Метод Path resolve(Path other)
Метод resolve() выполняет операцию, обратную relativize() : из абсолютного и относительного пути он строит новый абсолютный путь.
Path path1 = Path.of("projects\\note.txt"); Path path2 = Path.of("c:\\windows\\"); Path result = path1.resolve(path2);
"c:\\windows"
Path path1 = Path.of("projects\\note.txt"); Path path2 = Path.of("c:\\windows\\"); Path result = path2.resolve(path1);
"c:\\windows\\projects\\note.txt"
Метод toFile()
Метод возвращает устаревший объект File , который хранит тот же путь к файлу, что и объект Path .
Метод toURI()
Метод преобразует путь к стандарту URI , возвращает объект, который содержит путь к файлу:
c:\windows\projects\note.txt
file:///c:/windows/projects/note.txt
Путь к Java для Eclipse
Когда у вас на компьютере зоопарк из разных версий Java, то зачастую Eclipse будет запускаться с Java, которая была установлена последней. У меня, например, сложилась такая ситуация, что последней версией было JDK 9.0.1, но Eclipse у меня старый. Он, разумеется, вполне запускается и на новой версии Java, но в Java 9 было достаточно много изменений. Например, там были удалены “tools.jar” и “rt.jar”, а они используются некоторыми плагинами Maven-а.
Чтобы мой Eclipse снова заработал как надо, мне пришлось в “eclipse.ini” прописать аргумент -vm , который указывает путь к Java, с которой нужно запускать IDE.
В файле “eclipse.ini” важен порядок! Нужно обязательно указывать -vm до -vmargs !
В результате мой файл стал выглядеть вот так (у меня сборка Spring Tool Suite, там этот файл называется “STS.ini”, но по сути это тот же Eclipse, но с предустановленными плагинами):
Как правильно прописать путь к .png картинке в java?
Здравствуйте, пытаюсь прописать путь к изображению на java. Изображение находится в папке data, сама папка data лежит парралельно папке src. Строка, где считывается изображение:
Image cellTexture = new Image(getClass().getResourceAsStream("data\\Cell.png"));
Перепробовал всё, что нашёл в интернете, и ничего не работает. В другом проекте такой же путь коррекно приводит к файлу (текстовому) с таким же расположением. Спасибо за советы.
- Вопрос задан более двух лет назад
- 639 просмотров
2 комментария
Простой 2 комментария

pshevnin pshevnin вы хотели
положить Cell.png в src/main/resources/data и вызвать вот так
final String resourcePath = "data/Cell.png"; final Image cellTexture = new Image( getClass().getClassLoader().getResourceAsStream(resourcePath));
если помогло — отметьте решением