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.