Sådan undgår du Java FileNotFoundException, når du indlæser ressourcer

1. Oversigt

I denne vejledning undersøger vi et problem, der kan komme op, når man læser ressourcefiler i en Java-applikation: Ved kørsel er ressourcemappen sjældent den samme placering på disken som i vores kildekode.

Lad os se, hvordan Java giver os adgang til ressourcefiler, efter at vores kode er blevet pakket.

2. Læsning af filer

Lad os sige, at vores applikation læser en fil under opstart:

prøv (FileReader fileReader = ny FileReader ("src / main / resources / input.txt"); BufferedReader reader = ny BufferedReader (fileReader)) {String indhold = reader.lines () .collect (Collectors.joining (System.lineSeparator ( ))); }

Hvis vi kører ovenstående kode i en IDE, indlæses filen uden en fejl. Dette er fordi vores IDE bruger vores projektmappe som den aktuelle arbejdsmappe og src / main / ressourcer katalog er lige der for applikationen at læse.

Lad os nu sige, at vi bruger Maven JAR-pluginet til at pakke vores kode som en JAR.

Når vi kører det på kommandolinjen:

java -jar kerne-java-io2.jar

Vi får vist følgende fejl:

Undtagelse i tråd "main" java.io.FileNotFoundException: src / main / resources / input.txt (Ingen sådan fil eller katalog) på java.io.FileInputStream.open0 (Native Method) på java.io.FileInputStream.open (FileInputStream .java: 195) på java.io.FileInputStream. (FileInputStream.java:138) på java.io.FileInputStream. (FileInputStream.java:93) ved java.io.FileReader. (FileReader.java:58) på com. baeldung.resource.MyResourceLoader.loadResourceWithReader (MyResourceLoader.java:14) på ​​com.baeldung.resource.MyResourceLoader.main (MyResourceLoader.java:37)

3. Kildekode vs kompileret kode

Når vi bygger en JAR, placeres ressourcerne i rodmappen på de pakkede artefakter.

I vores eksempel ser vi kildekodeopsætningen har input.txt i src / main / ressourcer i vores kildekodemappe.

I den tilsvarende JAR-struktur ser vi dog:

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-filer / input.txt com / baeldung / ressource / MyResourceLoader.class META-INF / maven / com.baeldung / core-java-io-files / pom.xml META-INF / maven / com.baeldung / core-java-io-filer / pom.properties

Her, input.txt er i rodmappen til JAR. Så når koden udføres, ser vi FileNotFoundException.

Selv hvis vi ændrede stien til /input.txt den oprindelige kode kunne ikke indlæse denne fil som ressourcer kan normalt ikke adresseres som filer på disken. Ressourcefilerne er pakket inde i JAR, og vi har brug for en anden måde at få adgang til dem.

4. Ressourcer

Lad os i stedet bruge ressourceindlæsning til indlæse ressourcer fra klassestien i stedet for en bestemt filplacering. Dette fungerer uanset hvordan koden er pakket:

prøv (InputStream inputStream = getClass (). getResourceAsStream ("/ input.txt"); BufferedReader reader = ny BufferedReader (ny InputStreamReader (inputStream))) {String indhold = reader.lines () .collect (Collectors.joining (System. lineSeparator ())); }

ClassLoader.getResourceAsStream () ser på klassestien for den givne ressource. Den førende skråstreg på input til getResourceAsStream () fortæller læsseren om at læse fra bunden af ​​klassestien. Indholdet af vores JAR-fil er på klassestien, så denne metode fungerer.

En IDE inkluderer typisk src / main / ressourcer på sin klassesti og finder således filerne.

5. Konklusion

I denne hurtige artikel implementerede vi indlæsning af filer som classpath-ressourcer, så vores kode kunne fungere konsekvent uanset hvordan den blev pakket.

Som altid er eksempelkoden tilgængelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found