Hvordan unngå Java FileNotFoundException når du laster inn ressurser

1. Oversikt

I denne opplæringen vil vi utforske et problem som kan dukke opp når du leser ressursfiler i et Java-program: På kjøretid er ressursmappen sjelden på samme sted på disken som i kildekoden.

La oss se hvordan Java gir oss tilgang til ressursfiler etter at koden vår er pakket.

2. Lese filer

La oss si at applikasjonen vår leser en fil under oppstart:

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

Hvis vi kjører ovennevnte kode i en IDE, lastes filen uten feil. Dette er fordi vår IDE bruker prosjektkatalogen som gjeldende arbeidskatalog og src / main / resources katalogen er der for applikasjonen å lese.

La oss si at vi bruker Maven JAR-plugin for å pakke koden vår som en JAR.

Når vi kjører den på kommandolinjen:

java -jar core-java-io2.jar

Vi får se følgende feil:

Unntak i tråden "main" java.io.FileNotFoundException: src / main / resources / input.txt (Ingen slik 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) på 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 kompilert kode

Når vi bygger en JAR, blir ressursene plassert i rotkatalogen til de pakkede gjenstandene.

I vårt eksempel ser vi kildekodeoppsettet har input.txt i src / main / resources i vår kildekodekatalog.

I den tilsvarende JAR-strukturen ser vi imidlertid:

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 no / 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

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

Selv om vi endret stien til /input.txt den opprinnelige koden kunne ikke laste inn denne filen som ressurser kan vanligvis ikke adresseres som filer på disken. Ressursfilene er pakket inne i JAR, og derfor trenger vi en annen måte å få tilgang til dem.

4. Ressurser

La oss i stedet bruke ressurslast til last inn ressurser fra klassestien i stedet for en bestemt filplassering. Dette fungerer uavhengig av hvordan koden er pakket:

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

ClassLoader.getResourceAsStream () ser på klassestien for den gitte ressursen. Den ledende skråstrek på inngangen til getResourceAsStream () ber lasteren lese fra bunnen av klassestien. Innholdet i JAR-filen vår er på klassestien, så denne metoden fungerer.

En IDE inkluderer vanligvis src / main / resources på klassestien og finner dermed filene.

5. Konklusjon

I denne raske artikkelen implementerte vi innlasting av filer som classpath-ressurser, slik at koden vår kunne fungere uavhengig av hvordan den ble pakket.

Som alltid er eksempelkoden tilgjengelig på GitHub.


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