Hvordan lese en fil i Java

1. Oversikt

I denne opplæringen vil vi utforske forskjellige måter å lest fra en fil i Java.

Først får vi se hvordan du laster en fil fra klassestien, en URL eller fra en JAR-fil ved hjelp av standard Java-klasser.

For det andre får vi se hvordan vi kan lese innholdet med BufferedReader, Skanner, StreamTokenizer, DataInputStream, SekvensInputStream, og FileChannel. Vi vil også diskutere hvordan du leser en UTF-8-kodet fil.

Til slutt vil vi utforske de nye teknikkene for å laste inn og lese en fil i Java 7 og Java 8.

Denne artikkelen er en del av "Java - Back to Basic" -serien her på Baeldung.

2. Oppsett

2.1 Inndatafil

I de fleste eksempler i denne artikkelen vil vi lese en tekstfil med filnavn fileTest.txt som inneholder en linje:

Hei Verden!

I noen få eksempler bruker vi en annen fil. I disse tilfellene nevner vi filen og dens innhold eksplisitt.

2.2 Hjelpermetode

Vi vil bruke et sett med testeksempler som kun bruker Java-klasser, og i testene bruker vi påstander ved hjelp av Hamcrest-matchere.

Tester vil dele en felles readFromInputStream metode som forvandler en InputStream til String for lettere å hevde resultatene:

private String readFromInputStream (InputStream inputStream) kaster IOException {StringBuilder resultStringBuilder = new StringBuilder (); prøv (BufferedReader br = ny BufferedReader (ny InputStreamReader (inputStream))) {Strenglinje; mens ((line = br.readLine ())! = null) {resultStringBuilder.append (line) .append ("\ n"); }} returner resultatStringBuilder.toString (); }

Merk at det er andre måter å oppnå det samme resultatet på. Du kan konsultere denne artikkelen for noen alternativer.

3. Lese en fil fra klassestien

3.1. Bruke Standard Java

Denne delen forklarer hvordan du leser en fil som er tilgjengelig på en klassebane. Vi leser “ fileTest.txt ”Tilgjengelig under src / main / resources :

@Test offentlig ugyldig givenFileNameAsAbsolutePath_whenUsingClasspath_thenFileData () {String expectData = "Hei, verden!"; Class clazz = FileOperationsTest.class; InputStream inputStream = clazz.getResourceAsStream ("/ fileTest.txt"); Strengdata = readFromInputStream (inputStream); Assert.assertThat (data, inneholderString (forventetData)); }

I kodebiten ovenfor brukte vi den gjeldende klassen til å laste inn en fil med getResourceAsStream metoden og passerte den absolutte banen til filen som skal lastes inn.

Den samme metoden er tilgjengelig på en ClassLoader eksempel også:

ClassLoader classLoader = getClass () getClassLoader (); InputStream inputStream = classLoader.getResourceAsStream ("fileTest.txt"); Strengdata = readFromInputStream (inputStream);

Vi får tak i classLoader av gjeldende klasse ved hjelp av getClass (). getClassLoader () .

Hovedforskjellen er at når du bruker getResourceAsStream på en ClassLoader for eksempel blir stien behandlet som absolutt med utgangspunkt i roten til klassestien.

Når det brukes mot en Klasse forekomst , banen kan være i forhold til pakken, eller en absolutt bane, som er antydet av den ledende skråstrek.

Vær selvfølgelig oppmerksom på at åpne bekker i praksis alltid skal være stengt, slik som InputStream i vårt eksempel:

InputStream inputStream = null; prøv {File file = new File (classLoader.getResource ("fileTest.txt"). getFile ()); inputStream = ny FileInputStream (fil); // ...} til slutt {if (inputStream! = null) {prøv {inputStream.close (); } fange (IOException e) {e.printStackTrace (); }}}

3.2. Bruker commons-io Bibliotek

Et annet vanlig alternativ er å bruke FileUtils klasse av commons-io pakke:

@Test offentlig ugyldig givenFileName_whenUsingFileUtils_thenFileData () {String expectData = "Hei verden!"; ClassLoader classLoader = getClass () getClassLoader (); Filfil = ny fil (classLoader.getResource ("fileTest.txt"). GetFile ()); String data = FileUtils.readFileToString (fil, "UTF-8"); assertEquals (expectData, data.trim ()); }

Her passerer vi Fil motsette seg metoden readFileToString () av FileUtils klasse. Denne verktøysklassen klarer å laste innholdet uten at det er nødvendig å skrive noen kjelekode for å lage en InputStream forekomst og les data.

Det samme biblioteket tilbyr også IOUtilsklasse:

@Test offentlig ugyldig givenFileName_whenUsingIOUtils_thenFileData () {String expectData = "Hei verden!"; FileInputStream fis = ny FileInputStream ("src / test / resources / fileTest.txt"); Strengdata = IOUtils.toString (fis, "UTF-8"); assertEquals (expectData, data.trim ()); }

Her passerer vi FileInputStream motsette seg metoden toString () av IOUtils klasse. Denne verktøysklassen klarer å laste innholdet uten at det er nødvendig å skrive noen kjelekode for å lage en InputStream forekomst og les data.

4. Lesing med BufferedReader

La oss nå fokusere på forskjellige måter å analysere innholdet i en fil.

Vi begynner med en enkel måte å lese fra en fil ved hjelp av BufferedReader:

@Test offentlig ugyldig nårReadWithBufferedReader_thenCorrect () kaster IOException {String expect_value = "Hei verden!"; Strengfil; BufferedReader reader = ny BufferedReader (ny FileReader (fil)); Streng currentLine = reader.readLine (); reader.close (); assertEquals (forventet_verdi, nåværende linje); }

Noter det readLine () vil returnere null når slutten av filen er nådd.

5. Lese fra en fil ved hjelp av Java NIO

I JDK7 ble NIO-pakken betydelig oppdatert.

La oss se på et eksempel ved hjelp av Filer klasse og readAllLines metode. De readAllLines metoden godtar en Sti.

Sti klasse kan betraktes som en oppgradering av java.io. fil med noen ekstra operasjoner på plass.

5.1. Lese en liten fil

Følgende kode viser hvordan du leser en liten fil ved hjelp av den nye Filer klasse:

@Test offentlig ugyldig nårReadSmallFileJava7_thenCorrect () kaster IOException {String expect_value = "Hei verden!"; Banesti = Paths.get ("src / test / resources / fileTest.txt"); Streng lese = Files.readAllLines (sti) .get (0); assertEquals (forventet_verdi, lest); }

Merk at du kan bruke readAllBytes () metoden også hvis du trenger binære data.

5.2. Lese en stor fil

Hvis vi vil lese en stor fil med Filer klasse, kan vi bruke BufferedReader:

Følgende kode leser filen ved hjelp av den nye Filer klasse og BufferedReader:

@Test offentlig ugyldig nårReadLargeFileJava7_thenCorrect () kaster IOException {String expect_value = "Hei verden!"; Banesti = Paths.get ("src / test / resources / fileTest.txt"); BufferedReader reader = Files.newBufferedReader (sti); Strenglinje = reader.readLine (); assertEquals (forventet_verdi, linje); }

5.3. Lese en fil ved hjelp av Files.lines ()

JDK8 tilbyr linjer () metoden inne i Filer klasse. Det returnerer a Strøm av strengelementer.

La oss se på et eksempel på hvordan du leser data i byte og dekoder ved hjelp av UTF-8-tegnsett.

Følgende kode leser filen ved hjelp av den nye Files.lines ():

@Test offentlig ugyldig givenFilePath_whenUsingFilesLines_thenFileData () {String expectData = "Hei verden!"; Sti bane = Paths.get (getClass (). GetClassLoader () .getResource ("fileTest.txt"). ToURI ()); Strømlinjer = Files.lines (sti); Strengdata = lines.collect (Collectors.joining ("\ n")); linjer. lukk (); Assert.assertEquals (expectData, data.trim ()); }

Ved å bruke Stream med IO-kanaler som filoperasjoner, må vi lukke strømmen eksplisitt ved hjelp av Lukk() metode.

Som vi kan se, er Filer API tilbyr en annen enkel måte å lese filinnholdet inn i String.

I de neste avsnittene, la oss ta en titt på andre, mindre vanlige metoder for å lese en fil, som kan være passende i noen situasjoner.

6. Lesing med Skanner

La oss deretter bruke en Skanner å lese fra filen. Her bruker vi mellomrom som skilletegn:

@Test offentlig ugyldig nårReadWithScanner_thenCorrect () kaster IOException {String file = "src / test / resources / fileTest.txt"; Skannerskanner = ny skanner (ny fil (fil)); scanner.useDelimiter (""); assertTrue (scanner.hasNext ()); assertEquals ("Hello", scanner.next ()); assertEquals ("verden!", scanner.next ()); scanner.close (); }

Merk at standard skilletegn er det hvite området, men flere skillelinjer kan brukes med en Skanner.

Skannerklassen er nyttig når du leser innhold fra konsollen, eller når innholdet inneholder primitive verdier, med en kjent skillelinje (f.eks. en liste over heltall atskilt med mellomrom).

7. Lesing med StreamTokenizer

La oss deretter lese en tekstfil i tokens ved hjelp av a StreamTokenizer.

Måten tokenizer fungerer på er - først må vi finne ut hva neste token er - streng eller nummer; vi gjør det ved å se på tokenizer.ttype felt.

Deretter vil vi lese det faktiske tokenet basert på denne typen:

  • tokenizer.nval - hvis typen var et tall
  • tokenizer.sval - hvis typen var en streng

I dette eksemplet bruker vi en annen inndatafil som ganske enkelt inneholder:

Hei 1

Den følgende koden leser både streng og nummer fra filen:

@Test offentlig ugyldig nårReadWithStreamTokenizer_thenCorrectTokens () kaster IOException {String file = "src / test / resources / fileTestTokenizer.txt"; FileReader reader = ny FileReader (fil); StreamTokenizer tokenizer = ny StreamTokenizer (leser); // token 1 tokenizer.nextToken (); assertEquals (StreamTokenizer.TT_WORD, tokenizer.ttype); assertEquals ("Hei", tokenizer.sval); // token 2 tokenizer.nextToken (); assertEquals (StreamTokenizer.TT_NUMBER, tokenizer.ttype); assertEquals (1, tokenizer.nval, 0.0000001); // token 3 tokenizer.nextToken (); assertEquals (StreamTokenizer.TT_EOF, tokenizer.ttype); reader.close (); }

Legg merke til hvordan slutten av filtoken brukes på slutten.

Denne tilnærmingen er nyttig for å analysere en inngangsstrøm i tokens.

8. Lesing med DataInputStream

Vi kan bruke DataInputStream for å lese binær eller primitiv datatype fra en fil.

Følgende test leser filen ved hjelp av a DataInputStream:

@Test offentlig ugyldig nårReadWithDataInputStream_thenCorrect () kaster IOException {String expectValue = "Hei, verden!"; Strengfil; Strengresultat = null; DataInputStream-leser = ny DataInputStream (ny FileInputStream (fil)); int nBytesToRead = reader.available (); hvis (nBytesToRead> 0) {byte [] byte = ny byte [nBytesToRead]; reader.read (byte); resultat = ny streng (byte); } assertEquals (forventet verdi, resultat); }

9. Lesing med FileChannel

Hvis vi leser en stor fil, FileChannel kan være raskere enn standard IO.

Følgende kode leser databytes fra filen ved hjelp av FileChannel og RandomAccessFile:

@Test offentlig ugyldig nårReadWithFileChannel_thenCorrect () kaster IOException {String expect_value = "Hei verden!"; Strengfil = "src / test / resources / fileTest.txt"; RandomAccessFile reader = ny RandomAccessFile (fil, "r"); FileChannel channel = reader.getChannel (); int bufferSize = 1024; hvis (bufferSize> channel.size ()) {bufferSize = (int) channel.size (); } ByteBuffer buff = ByteBuffer.allocate (bufferSize); channel.read (buff); buff.flip (); assertEquals (forventet_verdi, ny streng (buff.array ())); channel.close (); reader.close (); }

10. Lese en UTF-8 kodet fil

La oss nå se hvordan du leser en UTF-8-kodet fil ved hjelp av BufferedReader. I dette eksemplet vil vi lese en fil som inneholder kinesiske tegn:

@Test offentlig ugyldig nårReadUTFEncodedFile_thenCorrect () kaster IOException {String expect_value = "青 空"; Strengfil = "src / test / resources / fileTestUtf8.txt"; BufferedReader reader = new BufferedReader (new InputStreamReader (new FileInputStream (file), "UTF-8")); Streng currentLine = reader.readLine (); reader.close (); assertEquals (forventet_verdi, nåværende linje); }

11. Lesing av innhold fra URL

For å lese innhold fra en URL vil vi bruke “/”URL i vårt eksempel som:

@Test offentlig ugyldig gittURLName_whenUsingURL_thenFileData () {String expectData = "Baeldung"; URL urlObject = ny URL ("/"); URLConnection urlConnection = urlObject.openConnection (); InputStream inputStream = urlConnection.getInputStream (); Strengdata = readFromInputStream (inputStream); Assert.assertThat (data, inneholderString (forventetData)); }

Det er også alternative måter å koble til en URL på. Her brukte vi URL og URLtilkobling klasse tilgjengelig i standard SDK.

12. Lese en fil fra en JAR

For å lese en fil som ligger i en JAR-fil, trenger vi en JAR med en fil i den. For eksempel vil vi lese “LISENS.txt" fra "hamcrest-library-1.3.jar”Fil:

@Test offentlig ugyldig givenFileName_whenUsingJarFile_thenFileData () {String expectData = "BSD License"; Class clazz = Matchers.class; InputStream inputStream = clazz.getResourceAsStream ("/ LICENSE.txt"); Strengdata = readFromInputStream (inputStream); Assert.assertThat (data, inneholderString (forventetData)); }

Her vil vi laste LISENS.txt som ligger i Hamcrest bibliotek, så vi vil bruke Matchers klasse som hjelper til med å skaffe en ressurs. Den samme filen kan også lastes inn ved hjelp av classloader.

13. Konklusjon

Som du kan se, er det mange muligheter for å laste inn en fil og lese data fra den ved hjelp av vanlig Java.

Du kan laste inn en fil fra forskjellige steder som classpath, URL eller jar-filer.

Da kan du bruke BufferedReader å lese linje for linje, Skanner å lese ved hjelp av forskjellige avgrensere, StreamTokenizer å lese en fil i tokens, DataInputStream å lese binære data og primitive datatyper, SekvensInngangsstrøm å koble flere filer til en strøm, FileChannel å lese raskere fra store filer osv.

Du finner kildekoden i følgende GitHub repo.


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