1. Обзор
В этом руководстве мы рассмотрим проблему, которая может возникнуть при чтении файлов ресурсов в Java-приложении: во время выполнения папка ресурсов редко находится в том же месте на диске, что и в нашем исходном коде.
Давайте посмотрим, как Java позволяет нам получать доступ к файлам ресурсов после того, как наш код был упакован.
2. Чтение Файлов
Допустим, наше приложение читает файл во время запуска:
try (FileReader fileReader = new FileReader("src/main/resources/input.txt"); BufferedReader reader = new BufferedReader(fileReader)) { String contents = reader.lines() .collect(Collectors.joining(System.lineSeparator())); }
Если мы запустим приведенный выше код в среде IDE, файл загрузится без ошибки. Это связано с тем, что наша ИДЕЯ использует каталог нашего проекта в качестве текущего рабочего каталога , а каталог src/main/resources находится прямо там, чтобы приложение могло читать.
Теперь предположим, что мы используем плагин Maven JAR для упаковки нашего кода в виде JAR.
Когда мы запускаем его в командной строке:
java -jar core-java-io2.jar
Мы увидим следующую ошибку:
Exception in thread "main" java.io.FileNotFoundException: src/main/resources/input.txt (No such file or directory) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(FileInputStream.java:195) at java.io.FileInputStream.(FileInputStream.java:138) at java.io.FileInputStream. (FileInputStream.java:93) at java.io.FileReader. (FileReader.java:58) at com.baeldung.resource.MyResourceLoader.loadResourceWithReader(MyResourceLoader.java:14) at com.baeldung.resource.MyResourceLoader.main(MyResourceLoader.java:37)
3. Исходный код и скомпилированный код
Когда мы создаем JAR, ресурсы помещаются в корневой каталог упакованных артефактов.
В нашем примере мы видим, что настройка исходного кода имеет input.txt в src/main/resources в нашем каталоге исходного кода.
Однако в соответствующей структуре БАНКИ мы видим:
META-INF/MANIFEST.MF META-INF/ com/ com/baeldung/ com/baeldung/resource/ META-INF/maven/ META-INF/maven/com.baeldung/ META-INF/maven/com.baeldung/core-java-io-files/ input.txt com/baeldung/resource/MyResourceLoader.class META-INF/maven/com.baeldung/core-java-io-files/pom.xml META-INF/maven/com.baeldung/core-java-io-files/pom.properties
Здесь, input.txt находится в корневом каталоге JAR. Поэтому, когда код будет выполнен, мы увидим исключение FileNotFoundException .
Даже если мы изменим путь на /input.txt исходный код не смог загрузить этот файл, так как ресурсы обычно не адресуются в виде файлов на диске. Файлы ресурсов упакованы в банку, и поэтому нам нужен другой способ доступа к ним.
4. Ресурсы
Давайте вместо этого используем загрузку ресурсов для загрузки ресурсов из пути к классу вместо определенного расположения файла. Это будет работать независимо от того, как упакован код:
try (InputStream inputStream = getClass().getResourceAsStream("/input.txt"); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { String contents = reader.lines() .collect(Collectors.joining(System.lineSeparator())); }
ClassLoader.getResourceAsStream() просматривает путь к классу для данного ресурса. Начальная косая черта на входе в getResourceAsStream() указывает загрузчику на чтение из базы пути к классу. Содержимое нашего файла JAR находится в пути к классу , поэтому этот метод работает.
IDE обычно включает src/main/resources в свой путь к классу и, таким образом, находит файлы.
5. Заключение
В этой краткой статье мы реализовали загрузку файлов в качестве ресурсов пути к классам, чтобы наш код работал последовательно независимо от того, как он был упакован.
Как всегда, пример кода доступен на GitHub .