Útmutató a BufferedReaderhez

1. Áttekintés

BufferedReader olyan osztály, amely leegyszerűsíti a szöveg beolvasását egy karakter beviteli adatfolyamból. Pufferolja a karaktereket a szöveges adatok hatékony olvasásának lehetővé tétele érdekében.

Ebben az oktatóanyagban megvizsgáljuk a BufferedReader osztály.

2. Mikor kell használni BufferedReader

Általánosságban, BufferedReader jól jön, ha bármilyen bemeneti forrásból akarunk szöveget olvasni, legyen szó fájlokról, foglalatokról vagy valami másról.

Egyszerűen fogalmazva, ez lehetővé teszi számunkra, hogy minimalizáljuk az I / O műveletek számát azáltal, hogy karakterdarabokat olvasunk és belső pufferben tároljuk. Míg a puffer rendelkezik adatokkal, az olvasó onnan fog olvasni, ahelyett, hogy közvetlenül az alatta lévő adatfolyamból származna.

2.1. Egy másik olvasó pufferelése

Mint a legtöbb Java I / O osztály, itt isBufferedReader megvalósítja Dekoratőr minta, vagyis azt várja, hogy a Olvasó konstruktorában. Ily módon lehetővé teszi számunkra, hogy rugalmasan kiterjesszük az a példányát Olvasó megvalósítás pufferelési funkcióval:

BufferedReader olvasó = new BufferedReader (új FileReader ("src / main / resources / input.txt"));

De, ha a pufferelés nem számít számunkra, akkor egyszerűen használhatjuk a FileReader közvetlenül:

FileReader olvasó = new FileReader ("src / main / resources / input.txt");

A pufferelés mellett BufferedReader néhány segítő funkciót is nyújt a fájlok soronkénti olvasásához. Tehát annak ellenére, hogy egyszerűbbnek tűnik a használata FileReader közvetlenül, BufferedReader nagy segítség lehet.

2.2. Adatfolyam pufferelése

Általánosságban, konfigurálhatjuk BufferedReader bármilyen bemeneti adatfolyamot vennimint mögöttes forrás. Meg tudjuk csinálni felhasználásával InputStreamReader és becsomagolja a konstruktorba:

BufferedReader olvasó = new BufferedReader (új InputStreamReader (System.in));

A fenti példában innen olvassuk System.in amely tipikusan a billentyűzetről érkező bemenetnek felel meg. Hasonlóképpen átadhatnánk egy bemeneti adatfolyamot olvasásra egy foglalatból, fájlból vagy bármilyen elképzelhető típusú szöveges bemenetből. Az egyetlen előfeltétel, hogy legyen megfelelő InputStream végrehajtása.

2.3. BufferedReader vs Scanner

Alternatívaként használhatnánk a Scanner osztály elérni ugyanazt a funkcionalitást, mint a BufferedReader.

E két osztály között azonban jelentős különbségek vannak, amelyek felhasználási esetünktől függően akár többé, akár kevésbé kényelmessé tehetik számunkra:

  • BufferedReader szinkronizált (szálbiztos), míg a Scanner nem
  • Scanner elemezni tudja a primitív típusokat és a karakterláncokat reguláris kifejezések segítségével
  • BufferedReader lehetővé teszi a puffer méretének megváltoztatását, miközben a Scanner fix puffermérettel rendelkezik
  • BufferedReader nagyobb az alapértelmezett puffermérete
  • Scanner elrejti IOException, miközben BufferedReader arra kényszerít minket, hogy kezeljük
  • BufferedReader általában gyorsabb, mint Scanner mert csak elemzés nélkül olvassa az adatokat

Ezeket szem előtt tartva ha egy fájlban elemezünk egyes jogkivonatokat, akkor Scanner kicsit természetesebbnek fogja érezni magát, mint BufferedReader. De egyszerre csak egy sort kell olvasni BufferedReader ragyog.

Ha szükséges, van egy útmutatónk is Scanner is.

3. Szöveg olvasása vele BufferedReader

Menjünk végig az a felépítésének, használatának és megsemmisítésének teljes folyamatán BufferReader megfelelően olvasható szöveges fájlból.

3.1. Inicializálás a BufferedReader

Először, hozzunk létre egy BufferedReader annak használatával BufferedReader (Reader) konstruktőr:

BufferedReader olvasó = new BufferedReader (új FileReader ("src / main / resources / input.txt"));

A FileReader ez egy jó módszer arra, hogy a pufferelést szempontként hozzáadjuk a többi olvasóhoz.

Alapértelmezés szerint ez 8 KB puffert fog használni. Ha azonban kisebb vagy nagyobb blokkokat akarunk pufferolni, használhatjuk a BufferedReader (Reader, int) konstruktőr:

BufferedReader reader = új BufferedReader (új FileReader ("src / main / resources / input.txt")), 16384);

Ezzel a puffer méretét 16384 bájtra (16 KB) állítja be.

Az optimális pufferméret olyan tényezőktől függ, mint a bemeneti adatfolyam típusa és a hardver, amelyen a kód fut. Ezért az ideális pufferméret eléréséhez kísérletezéssel magunknak kell megtalálnunk.

A legjobb, ha pufferméretként a 2-es erőket használja, mivel a legtöbb hardvereszköz 2-es teljesítményű, mint a blokk mérete.

Végül, van még egy praktikus módszer a BufferedReader használni a Fájlok segítő osztály tól java.nioAPI:

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

Létrehozásaígy ez egy jó mód a pufferelésre, ha egy fájlt akarunk olvasni, mert nem kell manuálisan létrehoznunk egy FileReader előbb, majd tekerje be.

3.2. Soronként olvasás

Ezután olvassuk el a fájl tartalmát a readLine módszer:

public String readAllLines (BufferedReader olvasó) dobja az IOException {StringBuilder content = new StringBuilder (); Vonósor; while ((line = olvasó.readLine ())! = null) {content.append (sor); content.append (System.lineSeparator ()); } return content.toString (); }

Ugyanazt tehetjük, mint fent, a vonalak a Java 8-ban bevezetett módszer kicsit egyszerűbben:

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

3.3. Az adatfolyam bezárása

A. Használata után BufferedReader, hívnunk kell Bezárás() módszer a hozzá kapcsolódó rendszererőforrások felszabadítására. Ez automatikusan megtörténik, ha a erőforrásokkal próbálkozzon Blokk:

try (BufferedReader olvasó = new BufferedReader (új FileReader ("src / main / resources / input.txt")))) {return readAllLines (olvasó); }

4. Egyéb hasznos módszerek

Most összpontosítsunk az itt elérhető különféle hasznos módszerekre BufferedReader.

4.1. Egyetlen karakter olvasása

Használhatjuk a olvas() módszer egyetlen karakter elolvasására. Olvassuk el a teljes tartalmat karakterenként, a patak végéig:

public String readAllCharsOneByOne (BufferedReader olvasó) dobja az IOException {StringBuilder content = new StringBuilder (); int érték; while ((érték = olvasó.olvasott ())! = -1) {tartalom.append ((char) érték); } return content.toString (); }

Ez beolvassa a karaktereket (ASCII-értékként visszaadva), és önteni őket char és csatolja őket az eredményhez. Ezt megismételjük a folyam végéig, amelyet a -1 válaszérték jelez a olvas() módszer.

4.2. Több karakter olvasása

Ha egyszerre több karaktert akarunk elolvasni, használhatjuk a módszert olvasni (char [] cbuf, int ki, int len):

public String readMultipleChars (BufferedReader olvasó) dobja az IOException {int length; char [] chars = új char [hossz]; int charsRead = olvasó.olvasott (karakterek, 0, hossz); Karakterlánc eredménye; if (charsRead! = -1) {eredmény = új String (karakterek, 0, charsRead); } else {eredmény = ""; } visszatérési eredmény; }

A fenti kód példában legfeljebb 5 karaktert olvashatunk be egy char tömbbe, és felépítünk belőle egy karakterláncot. Abban az esetben, ha az olvasási kísérlet során egyetlen karakter sem lett elolvasva (vagyis a stream végére értünk), akkor egyszerűen egy üres karakterláncot adunk vissza.

4.3. Karakterek kihagyása

Adott számú karaktert is kihagyhatunk a ugrás (hosszú n) módszer:

@Test public void givenBufferedReader_whensSkipChars_thenOk () dobja az IOException {StringBuilder eredmény = új StringBuilder (); try (BufferedReader olvasó = new BufferedReader (új StringReader ("1__2__3__4__5")))) {int érték; míg ((érték = olvasó.olvasott ())! = -1) {eredmény.append ((char) érték); olvasó.skip (2L); }} assertEquals ("12345", eredmény); }

A fenti példában egy bemeneti karakterláncból olvashatunk, amely két aláhúzással elválasztott számokat tartalmaz. A csak számokat tartalmazó karaktersorozat összeállításához kihagyjuk az aláhúzást a kihagy módszer.

4.4. Mark és Visszaállítás

Használhatjuk a jelölés (int readAheadLimit) és Visszaállítás() módszerek az adatfolyam bizonyos pozícióinak megjelölésére és későbbi visszatérésre. Kissé kitalált példaként használjuk Mark() és Visszaállítás() figyelmen kívül hagyni a patak elején található összes szóközt:

@Test public void givenBufferedReader_whenSkipsWhitespacesAtBeginning_thenOk () dobja az IOException {String eredményt; try (BufferedReader olvasó = new BufferedReader (új StringReader ("Lorem ipsum dolor sit amet.")))) {do {olvasó.jel (1); } while (Karakter.isWhitespace (olvasó.olvasott ())) reader.reset (); eredmény = olvasó.readLine (); } assertEquals ("Lorem ipsum dolor sit amet.", eredmény); }

A fenti példában a Mark() módszer az imént olvasott pozíció megjelölésére. Ha 1-es értéket ad, azt csak a kód fogja megjegyezni az előrejelzett karakterekre. Itt hasznos, mert ha meglátjuk az első nem fehér szóközű karakterünket, akkor visszamehetünk és újra elolvashatjuk azt a karaktert anélkül, hogy az egész folyamot újra feldolgoznánk. Anélkül, hogy megjelölnénk, elveszítenénk L utolsó húrunkban.

Ne feledje, hogy Mark() dobhat egy UnsupportedOperationException, elég gyakori társulni markSupported () meghívó kóddal Mark(). Pedig valójában itt nincs szükségünk rá. Azért mert markSupported () mindig igazra tér vissza BufferedReader.

Természetesen a fentieket valamilyen elegánsabban megtehetjük más módon is, és valóban Mark és Visszaállítás nem túl tipikus módszerek. Bár minden bizonnyal jól jönnek, amikor előre kell tekinteni.

5. Következtetés

Ebben a gyors bemutatóban megtanultuk, hogyan kell a karakterbeviteli folyamokat gyakorlati példán keresztül olvasni BufferedReader.

Végül a példák forráskódja elérhető a Github oldalon.