Vodič kroz BufferedReader

1. Pregled

BufferedReader je klasa koja pojednostavljuje čitanje teksta iz toka unosa znakova. Znakove sprema u bafer kako bi omogućio učinkovito čitanje tekstnih podataka.

U ovom uputstvu ćemo pogledati kako koristiti BufferedReader razred.

2. Kada koristiti BufferedReader

Općenito, BufferedReader dobro dođe ako želimo čitati tekst s bilo koje vrste ulaznih izvora, bilo da su to datoteke, utičnice ili nešto drugo.

Jednostavno rečeno, omogućuje nam smanjenje broja I / O operacija čitanjem dijelova znakova i spremanjem u interni međuspremnik. Iako me uspremnik ima podatke, čitač će čitati iz njega umjesto izravno iz temeljnog toka.

2.1. Spremanje drugog čitača u bafer

Kao i većina Java I / O klasa,BufferedReader provodi Uzorak dekoratora, što znači da očekuje a Čitač u svom konstruktoru. Na taj nam način omogućuje fleksibilno proširivanje instance a Čitač implementacija s funkcijom međuspremnika:

Čitač BufferedReader = novi BufferedReader (novi FileReader ("src / main / resources / input.txt"));

Ali, ako nam međuspremnik nije važan, mogli bismo koristiti samo Čitač datoteka direktno:

Čitač FileReader = novi FileReader ("src / main / resources / input.txt");

Pored međuspremnika, BufferedReader također nudi neke lijepe pomoćne funkcije za čitanje datoteka red po red. Dakle, iako se može činiti jednostavnijim za upotrebu Čitač datoteka direktno, BufferedReader može biti od velike pomoći.

2.2. Međuspremnik struje

Općenito, možemo konfigurirati BufferedReader uzeti bilo koju vrstu ulaznog tokakao temeljni izvor. To možemo učiniti pomoću InputStreamReader i umotavanje u konstruktor:

Čitač BufferedReader = novi BufferedReader (novi InputStreamReader (System.in));

U gornjem primjeru čitamo iz System.in što obično odgovara unosu s tipkovnice. Slično tome, mogli bismo proslijediti ulazni tok za čitanje iz utičnice, datoteke ili bilo koje zamislive vrste tekstualnog unosa. Jedini preduvjet je da postoji prikladan InputStream provedba za to.

2.3. BufferedReader vs Scanner

Kao alternativu mogli bismo koristiti Skener razreda kako bi se postigla ista funkcionalnost kao i kod BufferedReader.

Međutim, postoje značajne razlike između ove dvije klase koje ih mogu učiniti ili više ili manje prikladnima za nas, ovisno o našem slučaju upotrebe:

  • BufferedReader je sinkroniziran (bez niti) dok Scanner nije
  • Skener može raščlaniti primitivne tipove i nizove pomoću regularnih izraza
  • BufferedReader omogućuje promjenu veličine međuspremnika dok Scanner ima fiksnu veličinu međuspremnika
  • BufferedReader ima veću zadanu veličinu međuspremnika
  • Skener skriva IOException, dok BufferedReader prisiljava nas da to riješimo
  • BufferedReader je obično brži od Skener jer podatke samo čita bez raščlanjivanja

Imajući ovo na umu, ako raščlanjujemo pojedine tokene u datoteci, onda Skener osjećat ću se nešto prirodnije od BufferedReader. Ali, samo čitanje retka odjednom je gdje BufferedReader sjaji.

Ako je potrebno, imamo i vodič Skener također.

3. Čitanje teksta s BufferedReader

Prođimo kroz čitav postupak izgradnje, korištenja i uništavanja a BufferReader ispravno za čitanje iz tekstualne datoteke.

3.1. Inicijalizacija a BufferedReader

Prvo, stvorimo a BufferedReader koristeći svoj BufferedReader (čitač) konstruktor:

Čitač BufferedReader = novi BufferedReader (novi FileReader ("src / main / resources / input.txt"));

Omotavanje Čitač datoteka ovako je lijep način za dodavanje međuspremnika kao aspekta drugim čitateljima.

Prema zadanim postavkama upotrebljavat će se međuspremnik od 8 KB. Međutim, ako želimo spremiti manje ili veće blokove, možemo koristiti BufferedReader (Reader, int) konstruktor:

Čitač BufferedReader = novi BufferedReader (novi FileReader ("src / main / resources / input.txt"), 16384);

Ovo će postaviti veličinu međuspremnika na 16384 bajta (16 KB).

Optimalna veličina međuspremnika ovisi o čimbenicima poput vrste ulaznog toka i hardvera na kojem se kôd izvodi. Iz tog razloga, da bismo postigli idealnu veličinu međuspremnika, moramo je sami pronaći eksperimentiranjem.

Najbolje je koristiti potencijale 2 kao veličinu međuspremnika jer većina hardverskih uređaja ima snagu 2 kao veličinu bloka.

Konačno, postoji još jedan zgodan način za stvaranje a BufferedReader koristiti Datoteke klasa pomoćnika od java.nioAPI:

Čitač BufferedReader = Files.newBufferedReader (Paths.get ("src / main / resources / input.txt"))

Stvarajući gaovako je lijep način međuspremnika ako želimo pročitati datoteku jer ne moramo ručno stvarati datoteku Čitač datoteka prvo pa zamotajte.

3.2. Čitanje red po red

Dalje, pročitajmo sadržaj datoteke pomoću readLine metoda:

javni String readAllLines (čitač BufferedReader) baca IOException {StringBuilder content = new StringBuilder (); Linija niza; while ((line = reader.readLine ())! = null) {content.append (line); content.append (System.lineSeparator ()); } vratiti sadržaj.toString (); }

Možemo učiniti isto što i gore koristeći linije metoda uvedena u Javi 8 malo jednostavnije:

javni String readAllLinesWithStream (čitač BufferedReader) {return reader.lines () .collect (Collectors.joining (System.lineSeparator ())); }

3.3. Zatvaranje toka

Nakon korištenja BufferedReader, moramo ga nazvati Zatvoriti() metoda za oslobađanje svih resursa sustava povezanih s tim. To se radi automatski ako koristimo a pokušajte s resursima blok:

probajte (BufferedReader čitač = novi BufferedReader (novi FileReader ("src / main / resources / input.txt"))) {return readAllLines (čitač); }

4. Ostale korisne metode

Sada ćemo se usredotočiti na razne korisne metode dostupne u BufferedReader.

4.1. Čitanje jednog lika

Možemo koristiti čitati() metoda za čitanje jednog znaka. Pročitajmo cijeli sadržaj pojedinačno po znak do kraja streama:

javni String readAllCharsOneByOne (čitač BufferedReader) baca IOException {StringBuilder content = new StringBuilder (); int vrijednost; while ((value = reader.read ())! = -1) {content.append ((char) value); } vratiti sadržaj.toString (); }

Ovim će se pročitati znakovi (vraćeni kao ASCII vrijednosti) i prebaciti u ugljen i dodajte ih rezultatu. To ponavljamo do kraja toka, što je označeno vrijednošću odziva -1 iz čitati() metoda.

4.2. Čitanje više znakova

Ako želimo pročitati više znakova odjednom, možemo koristiti metodu čitanje (char [] cbuf, int off, int len):

javni String readMultipleChars (čitač BufferedReader) baca IOException {int length; char [] znakovi = novi char [duljina]; int charsRead = čitač.read (znakovi, 0, dužina); Rezultat niza; if (charsRead! = -1) {result = new String (chars, 0, charsRead); } ostalo {rezultat = ""; } vratiti rezultat; }

U gornjem primjeru koda čitat ćemo do 5 znakova u niz znakova i od njega konstruirati niz. U slučaju da u našem pokušaju čitanja nisu pročitani znakovi (tj. Došli smo do kraja streama), jednostavno ćemo vratiti prazan niz.

4.3. Preskakanje znakova

Također možemo preskočiti zadani broj znakova pozivanjem znaka preskočiti (dugo n) metoda:

@Test javna praznina givenBufferedReader_whensSkipChars_thenOk () baca IOException {StringBuilder rezultat = novi StringBuilder (); probajte (BufferedReader čitač = novi BufferedReader (novi StringReader ("1__2__3__4__5"))) {int vrijednost; while ((value = reader.read ())! = -1) {result.append ((char) value); čitač.skip (2L); }} assertEquals ("12345", rezultat); }

U gornjem primjeru čitamo iz ulaznog niza koji sadrži brojeve odvojene s dvije donje crte. Da bismo konstruirali niz koji sadrži samo brojeve, preskačemo donje crte pozivanjem znaka preskočiti metoda.

4.4. ocjena i resetirati

Možemo koristiti oznaka (int readAheadLimit) i resetirati () metode za označavanje neke pozicije u toku i povratak u nju kasnije. Kao pomalo izmišljeni primjer, poslužimo se ocjena() i resetirati () da zanemarimo sve razmake na početku streama:

@Test javna praznina givenBufferedReader_whenSkipsWhitespacesAtBeginning_thenOk () baca IOException {Rezultat niza; probajte (BufferedReader čitač = novi BufferedReader (novi StringReader ("Lorem ipsum dolor sit amet."))) {do {reader.mark (1); } while (Character.isWhitespace (reader.read ())) reader.reset (); rezultat = čitač.readLine (); } assertEquals ("Lorem ipsum dolor sit amet.", rezultat); }

U gornjem primjeru koristimo ocjena() metoda za označavanje položaja koji smo upravo pročitali. Davanje vrijednosti 1 znači da će samo kôd pamtiti oznaku za jedan znak naprijed. Ovdje je zgodno jer, nakon što vidimo svoj prvi znak koji nije razmak, možemo se vratiti i ponovno pročitati taj znak bez potrebe za ponovnom obradom cijelog toka. Bez oznake izgubili bismo L u našem posljednjem nizu.

Imajte na umu da zato ocjena() može baciti UnsupportedOperationException, prilično je uobičajeno udruživanje markSupported () s kodom koji poziva ocjena(). Iako nam ovdje zapravo ne treba. To je zato što markSupported () uvijek vraća true za BufferedReader.

Naravno, možda bismo to mogli učiniti malo elegantnije na druge načine, i zaista ocjena i resetirati nisu baš tipične metode. Svakako dobro dođu kad treba gledati unaprijed.

5. Zaključak

U ovom smo brzom vodiču naučili kako čitati struje unosa znakova na praktičnom primjeru pomoću BufferedReader.

Napokon, izvorni kod za primjere dostupan je na Githubu.