Kako čitati datoteku na Javi

1. Pregled

U ovom uputstvu istražit ćemo različite načine za čitati iz datoteke na Javi.

Prvo ćemo vidjeti kako učitati datoteku s puta puta, URL-a ili iz JAR datoteke, koristeći standardne Java klase.

Drugo, vidjet ćemo kako čitati sadržaj BufferedReader, Skener, StreamTokenizer, DataInputStream, SequenceInputStream, i FileChannel. Također ćemo razgovarati o tome kako čitati datoteku kodiranu UTF-8.

Na kraju ćemo istražiti nove tehnike za učitavanje i čitanje datoteke u Java 7 i Java 8.

Ovaj je članak dio serije "Java - Povratak na osnovno" ovdje na Baeldungu.

2. Postavljanje

2.1 Ulazna datoteka

U većini primjera u ovom članku čitat ćemo tekstualnu datoteku s imenom datoteke fileTest.txt koji sadrži jedan redak:

Pozdrav svijete!

U nekoliko primjera koristit ćemo drugu datoteku. U tim ćemo slučajevima datoteku i njezin sadržaj spomenuti izričito.

2.2 Pomoćna metoda

Upotrijebit ćemo niz primjera ispitivanja koristeći samo osnovne Java klase, a u testovima ćemo koristiti tvrdnje pomoću Hamcrest podudaranja.

Testovi će imati zajedničko readFromInputStream metoda koja transformira InputStream do Niz za lakše utvrđivanje rezultata:

privatni niz readFromInputStream (InputStream inputStream) baca IOException {StringBuilder resultStringBuilder = novi StringBuilder (); try (BufferedReader br = new BufferedReader (new InputStreamReader (inputStream))) {String line; while ((line = br.readLine ())! = null) {resultStringBuilder.append (line) .append ("\ n"); }} return resultStringBuilder.toString (); }

Imajte na umu da postoje i drugi načini postizanja istog rezultata. U ovom članku možete potražiti neke druge mogućnosti.

3. Čitanje datoteke s Classpath-a

3.1. Korištenje standardne Jave

Ovaj odjeljak objašnjava kako čitati datoteku koja je dostupna na putu predavanja. Pročitat ćemo " fileTest.txt ”Dostupno pod src / glavni / resursi :

@Test javna praznina givenFileNameAsAbsolutePath_whenUsingClasspath_thenFileData () {String očekujeData = "Zdravo, svijet!"; Klasa klazz = FileOperationsTest.class; InputStream inputStream = clazz.getResourceAsStream ("/ fileTest.txt"); Podaci niza = readFromInputStream (inputStream); Assert.assertThat (podaci, sadržiString (očekivani podaci)); }

U gornjem isječku koda koristili smo trenutnu klasu za učitavanje datoteke pomoću getResourceAsStream metodom i proslijedio apsolutni put datoteke za učitavanje.

Ista je metoda dostupna na a ClassLoader instanca također:

ClassLoader classLoader = getClass (). GetClassLoader (); InputStream inputStream = classLoader.getResourceAsStream ("fileTest.txt"); Podaci niza = readFromInputStream (inputStream);

Dobivamo classLoader trenutne klase koristeći getClass (). getClassLoader () .

Glavna razlika je u tome što kada se koristi getResourceAsStream na a ClassLoader primjerice, put se tretira kao apsolutni počevši od korijena staze.

Kada se koristi protiv a Razred primjer , put može biti u odnosu na paket ili apsolutni put, što nagovještava vodeća kosa crta.

Naravno, imajte na umu da u praksi otvoreni tokovi uvijek trebaju biti zatvoreni, kao InputStream u našem primjeru:

InputStream inputStream = null; isprobajte {File file = new File (classLoader.getResource ("fileTest.txt"). getFile ()); inputStream = novi FileInputStream (datoteka); // ...} konačno {if (inputStream! = null) {try {inputStream.close (); } catch (IOException e) {e.printStackTrace (); }}}

3.2. Koristiti zajedničko-io Knjižnica

Druga uobičajena opcija je korištenje FileUtils klasa zajedničko-io paket:

@Test javna praznina givenFileName_whenUsingFileUtils_thenFileData () {String očekujeData = "Zdravo, svijet!"; ClassLoader classLoader = getClass (). GetClassLoader (); Datoteka datoteka = nova datoteka (classLoader.getResource ("fileTest.txt"). GetFile ()); Podaci niza = FileUtils.readFileToString (datoteka, "UTF-8"); assertEquals (očekuje seData, data.trim ()); }

Ovdje prolazimo Datoteka prigovoriti metodi readFileToString () od FileUtils razred. Ova klasa uslužnih programa uspijeva učitati sadržaj bez potrebe za pisanjem bilo kakvog koda za izradu InputStream instance i čita podatke.

Ista knjižnica nudi i IOUtilsrazred:

@Test javna praznina givenFileName_whenUsingIOUtils_thenFileData () {String očekujeData = "Zdravo, svijet!"; FileInputStream fis = novi FileInputStream ("src / test / resources / fileTest.txt"); Podaci o nizu = IOUtils.toString (fis, "UTF-8"); assertEquals (očekuje seData, data.trim ()); }

Ovdje prolazimo FileInputStream prigovoriti metodi toString () od IOUtils razred. Ova klasa uslužnih programa uspijeva učitati sadržaj bez potrebe za pisanjem bilo kakvog koda za izradu InputStream instance i čita podatke.

4. Čitanje s BufferedReader

Usredotočimo se sada na različite načine raščlanjivanja sadržaja datoteke.

Počet ćemo s jednostavnim načinom čitanja iz datoteke pomoću Puferirani čitač:

@Test public void whenReadWithBufferedReader_thenCorrect () baca IOException {String očekuje_value = "Zdravo, svijete!"; String datoteka; Čitač BufferedReader = novi BufferedReader (novi FileReader (datoteka)); Niz currentLine = reader.readLine (); reader.close (); assertEquals (očekivana_vrijednost, trenutna linija); }

Imajte na umu da readLine () će se vratiti null kad se dosegne kraj datoteke.

5. Čitanje iz datoteke pomoću Java NIO

U JDK7 NIO paket je značajno ažuriran.

Pogledajmo primjer pomoću Datoteke razred i readAllLines metoda. The readAllLines metoda prihvaća a Staza.

Staza razred može se smatrati nadogradnjom java.io.Datoteka s nekim dodatnim operacijama.

5.1. Čitanje male datoteke

Sljedeći kod prikazuje kako čitati malu datoteku pomoću nove Datoteke razred:

@Test public void whenReadSmallFileJava7_thenCorrect () baca IOException {String očekuje_value = "Zdravo, svijete!"; Put puta = Paths.get ("src / test / resources / fileTest.txt"); Čitanje niza = Files.readAllLines (put) .get (0); assertEquals (očekivana_vrijednost, pročitana); }

Imajte na umu da možete koristiti readAllBytes () metodu ako trebate binarne podatke.

5.2. Čitanje velike datoteke

Ako želimo pročitati veliku datoteku s Datoteke klase, možemo koristiti Puferirani čitač:

Sljedeći kod čita datoteku pomoću novog Datoteke razred i BufferedReader:

@Test public void whenReadLargeFileJava7_thenCorrect () baca IOException {String očekuje_value = "Zdravo, svijete!"; Put puta = Paths.get ("src / test / resources / fileTest.txt"); Čitač BufferedReader = Files.newBufferedReader (put); Linija niza = reader.readLine (); assertEquals (očekivana_vrijednost, crta); }

5.3. Čitanje datoteke pomoću Files.lines ()

JDK8 nudi linije () metoda unutar Datoteke razred. Vraća a Stream String elemenata.

Pogledajmo primjer kako čitati podatke u bajtove i dekodirati pomoću UTF-8 charset-a.

Sljedeći kod čita datoteku pomoću novog Files.lines ():

@Test javna praznina givenFilePath_whenUsingFilesLines_thenFileData () {String očekujeData = "Pozdrav, svijet!"; Put puta = Paths.get (getClass (). GetClassLoader () .getResource ("fileTest.txt"). ToURI ()); Linije strujanja = Files.lines (put); Podaci niza = lines.collect (Collectors.joining ("\ n")); linije.close (); Assert.assertEquals (očekuje seData, data.trim ()); }

Koristeći Stream s IO kanalima poput operacija datoteka, moramo eksplicitno zatvoriti stream koristeći Zatvoriti() metoda.

Kao što vidimo, Datoteke API nudi još jedan jednostavan način za čitanje sadržaja datoteke u Niz.

U sljedećim odjeljcima pogledajmo druge, rjeđe metode čitanja datoteke, koje bi mogle biti prikladne u nekim situacijama.

6. Čitanje sa Skener

Dalje, upotrijebimo a Skener čitati iz Datoteke. Ovdje ćemo za razgraničenje upotrijebiti razmak:

@Test public void whenReadWithScanner_thenCorrect () baca IOException {String file = "src / test / resources / fileTest.txt"; Skener skenera = novi skener (nova datoteka (datoteka)); scanner.useDelimiter (""); assertTrue (scanner.hasNext ()); assertEquals ("Pozdrav,", scanner.next ()); assertEquals ("svijet!", scanner.next ()); scanner.close (); }

Imajte na umu da je zadani graničnik razmak, ali više se graničnika može koristiti s Skener.

Klasa Scanner korisna je kada čitate sadržaj s konzole ili kada sadržaj sadrži primitivne vrijednosti, s poznatim graničnikom (npr .: popis cijelih brojeva odvojenih razmakom).

7. Čitanje sa StreamTokenizer

Dalje, pročitajmo tekstualnu datoteku u tokene pomoću a StreamTokenizer.

Način na koji tokenizer djeluje je - prvo, moramo shvatiti što je sljedeći token - Niz ili broj; to radimo gledajući tokenizer.tip polje.

Zatim ćemo pročitati stvarni token na temelju ove vrste:

  • tokenizer.nval - ako je vrsta broj
  • tokenizer.sval - ako je vrsta bila niz

U ovom ćemo primjeru koristiti drugu ulaznu datoteku koja jednostavno sadrži:

Pozdrav 1

Sljedeći kod čita iz datoteke i niz i broj:

@Test public void whenReadWithStreamTokenizer_thenCorrectTokens () baca IOException {String file = "src / test / resources / fileTestTokenizer.txt"; Čitač FileReader = novi FileReader (datoteka); StreamTokenizer tokenizer = novi StreamTokenizer (čitač); // token 1 tokenizer.nextToken (); assertEquals (StreamTokenizer.TT_WORD, tokenizer.ttype); assertEquals ("Zdravo", tokenizer.sval); // token 2 tokenizer.nextToken (); assertEquals (StreamTokenizer.TT_NUMBER, tokenizer.ttype); assertEquals (1, tokenizer.nval, 0,0000001); // žeton 3 tokenizer.nextToken (); assertEquals (StreamTokenizer.TT_EOF, tokenizer.ttype); čitač.close (); }

Imajte na umu kako se kraj tokena datoteke koristi na kraju.

Ovaj je pristup koristan za raščlanjivanje ulaznog toka na tokene.

8. Čitanje sa DataInputStream

Možemo koristiti DataInputStream za čitanje binarnog ili primitivnog tipa podataka iz datoteke.

Sljedeći test čita datoteku pomoću a DataInputStream:

@Test public void whenReadWithDataInputStream_thenCorrect () baca IOException {String očekujeValue = "Hello, world!"; String datoteka; Rezultat niza = null; DataInputStream čitač = novi DataInputStream (novi FileInputStream (datoteka)); int nBytesToRead = reader.available (); if (nBytesToRead> 0) {byte [] bytes = novi bajt [nBytesToRead]; reader.read (bajtovi); rezultat = novi niz (bajtovi); } assertEquals (očekuje seVrijednost, rezultat); }

9. Čitanje s FileChannel

Ako čitamo veliku datoteku, FileChannel može biti brži od standardnog IO-a.

Sljedeći kôd čita bajtove podataka iz datoteke pomoću FileChannel i RandomAccessFile:

@Test public void whenReadWithFileChannel_thenCorrect () baca IOException {String očekuje_value = "Zdravo, svijete!"; String datoteka = "src / test / resources / fileTest.txt"; Čitač RandomAccessFile = novi RandomAccessFile (datoteka, "r"); FileChannel channel = čitač.getChannel (); int bufferSize = 1024; if (bufferSize> channel.size ()) {bufferSize = (int) channel.size (); } ByteBuffer buff = ByteBuffer.allocate (bufferSize); channel.read (buff); buff.flip (); assertEquals (očekivana_vrijednost, novi niz (buff.array ())); channel.close (); čitač.close (); }

10. Čitanje UTF-8 kodirane datoteke

Pogledajmo sada kako čitati datoteku kodiranu UTF-8 BufferedReader. U ovom ćemo primjeru pročitati datoteku koja sadrži kineske znakove:

@Test public void whenReadUTFEncodedFile_thenCorrect () baca IOException {String očekuje_value = "青 空"; String datoteka = "src / test / resources / fileTestUtf8.txt"; Čitač BufferedReader = novi BufferedReader (novi InputStreamReader (novi FileInputStream (datoteka), "UTF-8")); Niz currentLine = reader.readLine (); čitač.close (); assertEquals (očekivana_vrijednost, trenutna linija); }

11. Čitanje sadržaja s URL-a

Za čitanje sadržaja s URL-a koristit ćemo "/”URL u našem primjeru kao:

@Test javna praznina danaURLName_whenUsingURL_thenFileData () {String očekujeData = "Baeldung"; URL urlObject = novi URL ("/"); URLConnection urlConnection = urlObject.openConnection (); InputStream inputStream = urlConnection.getInputStream (); Podaci niza = readFromInputStream (inputStream); Assert.assertThat (podaci, sadržiString (očekivani podaci)); }

Postoje i alternativni načini povezivanja s URL-om. Ovdje smo koristili URL i URLConnection klasa dostupna u standardnom SDK-u.

12. Čitanje datoteke iz JAR-a

Da bismo pročitali datoteku koja se nalazi unutar JAR datoteke, trebat će nam JAR s datotekom unutar nje. Za naš ćemo primjer pročitati „LICENCA.txt" od "hamcrest-knjižnica-1.3.jar" datoteka:

@Test javna praznina givenFileName_whenUsingJarFile_thenFileData () {String očekujeData = "BSD licenca"; Razred klaza = Matchers.class; InputStream inputStream = clazz.getResourceAsStream ("/ LICENSE.txt"); Podaci niza = readFromInputStream (inputStream); Assert.assertThat (podaci, sadržiString (očekivani podaci)); }

Ovdje želimo učitati LICENCA.txt koja se nalazi u Hamcrest knjižnici, pa ćemo koristiti Matcherova razred koji pomaže u dobivanju resursa. Ista datoteka se može učitati i pomoću učitača razreda.

13. Zaključak

Kao što vidite, postoji mnogo mogućnosti za učitavanje datoteke i čitanje podataka iz nje pomoću obične Jave.

Datoteku možete učitati s različitih mjesta kao što su put puta, URL-a ili jar datoteke.

Tada možete koristiti BufferedReader čitati redak po redak, Skener čitati pomoću različitih graničnika, StreamTokenizer za čitanje datoteke u tokene, DataInputStream za čitanje binarnih podataka i primitivnih vrsta podataka, Tok unosa SequenceInput za povezivanje više datoteka u jedan tok, FileChannel za brže čitanje iz velikih datoteka itd.

Izvorni kod možete pronaći u sljedećem GitHub repo-u.