So vermeiden Sie die Java FileNotFoundException beim Laden von Ressourcen

1. Übersicht

In diesem Lernprogramm werden wir ein Problem untersuchen, das beim Lesen von Ressourcendateien in einer Java-Anwendung auftreten kann: Zur Laufzeit befindet sich der Ressourcenordner selten an derselben Stelle auf der Festplatte wie in unserem Quellcode.

Mal sehen, wie Java es uns ermöglicht, auf Ressourcendateien zuzugreifen, nachdem unser Code gepackt wurde.

2. Dateien lesen

Angenommen, unsere Anwendung liest beim Start eine Datei:

try (FileReader fileReader = new FileReader("src/main/resources/input.txt"); BufferedReader reader = new BufferedReader(fileReader)) { String contents = reader.lines() .collect(Collectors.joining(System.lineSeparator())); }

Wenn wir den obigen Code in einer IDE ausführen, wird die Datei ohne Fehler geladen. Dies liegt daran, dass unsere IDE unser Projektverzeichnis als aktuelles Arbeitsverzeichnis verwendet und das Verzeichnis src / main / resources genau dort ist, wo die Anwendung es lesen kann.

Angenommen, wir verwenden das Maven JAR-Plugin, um unseren Code als JAR zu verpacken.

Wenn wir es über die Befehlszeile ausführen:

java -jar core-java-io2.jar

Wir werden den folgenden Fehler sehen:

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. Quellcode vs kompilierter Code

Wenn wir eine JAR erstellen, werden die Ressourcen im Stammverzeichnis der gepackten Artefakte abgelegt.

In unserem Beispiel sehen wir, dass das Quellcode-Setup input.txt in src / main / resources in unserem Quellcode-Verzeichnis hat.

In der entsprechenden JAR-Struktur sehen wir jedoch:

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

Hier befindet sich input.txt im Stammverzeichnis der JAR. Wenn der Code ausgeführt wird, wird die FileNotFoundException angezeigt .

Selbst wenn wir den Pfad zu /input.txt geändert haben, konnte der ursprüngliche Code diese Datei nicht laden, da Ressourcen normalerweise nicht als Dateien auf der Festplatte adressierbar sind. Die Ressourcendateien sind in der JAR gepackt, daher benötigen wir eine andere Art des Zugriffs auf sie.

4. Ressourcen

Verwenden wir stattdessen das Laden von Ressourcen, um Ressourcen aus dem Klassenpfad anstelle eines bestimmten Speicherorts zu laden . Dies funktioniert unabhängig davon, wie der Code verpackt ist:

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 () überprüft den Klassenpfad für die angegebene Ressource. Der führende Schrägstrich in der Eingabe von getResourceAsStream () weist den Loader an, von der Basis des Klassenpfads zu lesen. Der Inhalt unserer JAR-Datei befindet sich im Klassenpfad , daher funktioniert diese Methode.

Eine IDE enthält normalerweise src / main / resources in ihrem Klassenpfad und findet somit die Dateien.

5. Schlussfolgerung

In diesem kurzen Artikel haben wir das Laden von Dateien als Klassenpfadressourcen implementiert, damit unser Code unabhängig davon, wie er gepackt wurde, konsistent funktioniert.

Wie immer ist der Beispielcode auf GitHub verfügbar.