Cara Menghindari FileNotFoundException Java Saat Memuat Sumber Daya

1. Ikhtisar

Dalam tutorial ini, kita akan membahas masalah yang bisa muncul saat membaca file sumber daya dalam aplikasi Java: Saat runtime, folder sumber daya jarang berada di lokasi yang sama di disk seperti di kode sumber kita.

Mari kita lihat bagaimana Java memungkinkan kita mengakses file sumber daya setelah kode kita dikemas.

2. Membaca File

Katakanlah aplikasi kita membaca file selama startup:

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

Jika kita menjalankan kode di atas dalam IDE, file akan dimuat tanpa kesalahan. Ini karena IDE kita menggunakan direktori proyek kita sebagai direktori kerja saat ini dan direktori src / main / resources ada di sana untuk dibaca aplikasi.

Sekarang katakanlah kita menggunakan plugin Maven JAR untuk mengemas kode kita sebagai JAR.

Saat kami menjalankannya di baris perintah:

java -jar core-java-io2.jar

Kami akan melihat kesalahan berikut:

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. Kode Sumber vs Kode yang Dikompilasi

Saat kita membangun JAR, sumber daya ditempatkan ke direktori root dari artefak yang dikemas.

Dalam contoh kami, kami melihat pengaturan kode sumber memiliki input.txt di src / main / resources di direktori kode sumber kami.

Namun, dalam struktur JAR yang sesuai, kita melihat:

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

Di sini, input.txt ada di direktori root JAR. Jadi saat kode dijalankan, kita akan melihat FileNotFoundException .

Meskipun kami mengubah jalur ke /input.txt , kode asli tidak dapat memuat file ini karena sumber daya biasanya tidak dapat dialamatkan sebagai file pada disk. File sumber daya dikemas di dalam JAR sehingga kami memerlukan cara lain untuk mengaksesnya.

4. Sumber Daya

Sebagai gantinya, gunakan pemuatan sumber daya untuk memuat sumber daya dari classpath daripada lokasi file tertentu. Ini akan berfungsi terlepas dari bagaimana kode dikemas:

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 () melihat classpath untuk sumber daya yang diberikan. Garis miring di depan masukan ke getResourceAsStream () memberi tahu loader untuk membaca dari dasar classpath. Konten file JAR kita ada di classpath , jadi metode ini berfungsi.

IDE biasanya menyertakan src / main / resources di classpath-nya dan, dengan demikian, menemukan file-file tersebut.

5. Kesimpulan

Dalam artikel singkat ini, kami mengimplementasikan pemuatan file sebagai sumber classpath, untuk memungkinkan kode kami bekerja secara konsisten terlepas dari bagaimana itu dikemas.

Seperti biasa, kode contoh tersedia di GitHub.