Cara Mengelakkan Java FileNotFoundException Semasa Memuatkan Sumber

1. Gambaran keseluruhan

Dalam tutorial ini, kita akan meneroka masalah yang dapat muncul ketika membaca fail sumber dalam aplikasi Java: Pada waktu runtime, folder sumber jarang berada di lokasi yang sama pada disk seperti yang terdapat dalam kod sumber kami.

Mari lihat bagaimana Java membenarkan kita mengakses fail sumber setelah kod kita dibungkus.

2. Membaca Fail

Katakanlah aplikasi kami membaca fail semasa permulaan:

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

Sekiranya kita menjalankan kod di atas dalam IDE, fail akan dimuat tanpa kesalahan. Ini kerana IDE kami menggunakan direktori projek kami sebagai direktori kerjanya sekarang dan direktori src / main / resources ada di sana untuk aplikasi dibaca.

Sekarang katakan kita menggunakan plugin Maven JAR untuk mengemas kod kita sebagai JAR.

Semasa kami menjalankannya di baris arahan:

java -jar core-java-io2.jar

Kami akan melihat ralat 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. Kod Sumber vs Kod Tersusun

Semasa kita membina JAR, sumber daya dimasukkan ke dalam direktori root artifak yang dikemas.

Dalam contoh kami, kami melihat penyediaan kod sumber mempunyai input.txt dalam src / main / sumber dalam direktori kod sumber kami.

Walau bagaimanapun, 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. Oleh itu, apabila kod dijalankan, kita akan melihat FileNotFoundException .

Walaupun kita mengubah jalan ke /input.txt , kod asalnya tidak dapat memuat fail ini kerana sumber daya biasanya tidak dapat dialamatkan sebagai fail pada cakera. Fail sumber dikemas di dalam JAR dan kami memerlukan cara lain untuk mengaksesnya.

4. Sumber

Mari kita gunakan pemuatan sumber untuk memuatkan sumber dari jalan kelas dan bukannya lokasi fail tertentu. Ini akan berfungsi tanpa mengira kodnya dibungkus:

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 yang diberikan. Slash utama pada input untuk getResourceAsStream () memberitahu pemuat untuk membaca dari dasar jalan kelas. Kandungan fail JAR kami ada di classpath , jadi kaedah ini berfungsi.

IDE biasanya merangkumi src / main / resource pada classpathnya dan, dengan itu, mencari fail.

5. Kesimpulan

Dalam artikel ringkas ini, kami menerapkan memuatkan fail sebagai sumber classpath, untuk membolehkan kod kami berfungsi secara konsisten tanpa mengira bagaimana ia dikemas.

Seperti biasa, kod contoh boleh didapati di GitHub.