CodeGym /Java blog /Véletlen /Olvasás a billentyűzetről: "olvasók"
John Squirrels
Szint
San Francisco

Olvasás a billentyűzetről: "olvasók"

Megjelent a csoportban
Szia! A 3. szintű leckék és feladatok megtanították neked, hogyan jeleníts meg dolgokat a konzolon, és a másik irányba haladva hogyan olvass el adatokat a billentyűzetről.
Olvasás a billentyűzetről: "olvasók" - 1
Még a következő összetett konstrukciót is megtanultad ennek megvalósítására:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
De van egy kérdés, amire még nem válaszoltunk.

Hogy a világban működik ez?

A valóságban a programok ritkán teljesen függetlenek. Kommunikálnak más programokkal, rendszerekkel, az Internettel stb. A "kommunikáció" alatt elsősorban az "adatcserét" értjük. Vagyis kapnak valamilyen külső adatot, és belső programadatokat is küldenek valahova. A mindennapi életben bővelkedik példák adatcserére. Számos webhely például lehetővé teszi, hogy regisztráció helyett Facebook- vagy Twitter-fiókjával jelentkezzen be. Ebben a helyzetben két program (pl. Twitter és a webhely, amelyre bejelentkezik) kicseréli a szükséges adatokat. A végeredmény az, hogy sikeresen bejelentkezett. A "stream" szóaz adatcsere folyamatának leírására szolgál. Honnan jött ez a név? Tapasztalata szerint a "patak" inkább a folyókhoz és a programozáshoz köthető. Ez nem véletlen :) A folyam lényegében egy mozgó adat. Más szóval, a programozásban nem víz folyik, hanem adat bájtok és karakterek formájában. Adatok bitjeit fogadhatjuk egy adatfolyamból, majd felhasználhatjuk azokat. Ismét a víz/áramlás hasonlatot használjuk: vizet meríthetsz a folyóból, hogy levest főzzön, tüzet olts vagy meglocsold a virágaidat. Az adatfolyamok segítségével bármilyen adatforrással dolgozhat: legyen az internet, a számítógép fájlrendszere vagy valami más – ez nem számít. A streamek egy univerzális eszköz. Lehetővé teszik a programok számára, hogy bárhonnan adatokat fogadjanak (bemeneti adatfolyamok), és bárhová elküldjék (kimeneti adatfolyamok). Feladatuk ugyanaz: az egyik helyről adatokat venni és elküldeni egy másik helyre. Kétféle adatfolyam létezik:
  1. A bemeneti adatfolyamok az adatok fogadására szolgálnak
  2. A kimeneti adatfolyamok adatok küldésére szolgálnak.
InputStreamA Java nyelven ezeket a folyamokat a és osztályok valósítják meg OutputStream. De a patakokat másképpen is be lehet sorolni. A bemeneti és kimeneti adatfolyamokon kívül bájtfolyamokról és karakterfolyamokról is beszélünk . A jelentésnek itt elég világosnak kell lennie: a byte stream bájtok halmazaként küldi el az információt, míg a karakterfolyam karakterkészletként küldi el. Ebben a leckében a bemeneti adatfolyamokon fogunk foglalkozni. A lecke végére teszek egy linket a kimeneti adatfolyamokkal kapcsolatos információkkal. Egyedül is elolvashatod :) Most nézd meg ezt a kódot:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Amikor végigment a leckéken, nem gondoltad, hogy ez a vonal meglehetősen megfélemlítő? :) Ez nem lesz így, ha utánajártunk, hogyan működik. Tegyük rendbe a dolgokat. A végén kezdjük. System.inegy InputStreamobjektum, egy példánya annak az osztálynak, amelyről korán beszéltünk. Ez egy beviteli adatfolyam, amely a rendszer beviteli eszközéhez (a billentyűzethez) kapcsolódik. Egyébként közvetve ismered ezt az adatfolyamot. Végül is gyakran használja a „munkatársát” – System.out! System.outa rendszer kimeneti adatfolyama. Az adatok konzolra való kiküldésére szolgál kedvenc módszerén keresztül System.out.println(), amelyet folyamatosan használ :) System.outegy adatfolyam a konzolra történő adatküldéshez, mígSystem.inaz adatok lekérésére szolgál a billentyűzetről. Egyszerű az egész :) Ráadásul a billentyűzetről e hatalmas konstrukció nélkül is tudunk adatokat olvasni. Egyszerűen leírhatjuk: System.in.read();

public class Main {

   public static void main(String[] args) throws IOException {

       while (true) {
           int x = System.in.read();
           System.out.println(x);
       }
   }
}
Az InputStreamosztály (ne feledje, System.inegy InputStreamobjektum) rendelkezik egy read()metódussal, amely lehetővé teszi az adatok olvasását. Egy probléma van: bájtokat olvas , nem karaktereket . Unalmas csak angol betűket használni, ezért próbáljuk meg kiolvasni a "魚" kínai karaktert a billentyűzetről (csak másolja ki ezt a betűt innen, és illessze be a konzolba a ctrl + v használatával PC-n vagy a Command + v billentyűkombinációval Mac - en ). Ez a karakter egyébként "halat" jelent. Konzol kimenet: 233 173 154 10 Ez a szimbólum és sok más kínai 3 bájtot foglal el a számítógép memóriájában (ellentétben a latin betűkkel, amelyek mindössze 1 bájtot foglalnak el). Ebben az esetben 4 bájt kerül kiolvasásra az adatfolyamból: az első három a "魚" karaktert jelenti, a másik bájt pedig egy új sort (Enter). Ennek megfelelően System.indísztelen formában számunkra nem választható. Az emberek (ritka kivételektől eltekintve!) nem tudják, hogyan kell bájtokat olvasni. De az InputStreamReaderosztály jön a mentő! Lássuk, milyen állat ez.

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
Továbblépünk System.inaz InputStreamReader objektumhoz. Az osztály neve mondja! Létrehozunk egy InputStreamReaderobjektumot, és átadunk neki egy bemeneti adatfolyamot, amelyből adatokat fog olvasni. Ebben az esetben...

new InputStreamReader(System.in)
...azt mondjuk, hogy "adatokat fog olvasni a rendszer bemeneti adatfolyamából (a billentyűzetről)". De nem ez az egyetlen funkciója! A InputStreamReadernem csak az adatfolyamból fogad adatokat. Ezenkívül a bájtfolyamokat karakterfolyamokká alakítja . Más szóval, többé nem kell az adatokat „egyesekből és nullákból” „ember által olvasható nyelvvé” alakítani. InputStreamreadermindent megtesz érted. Természetesen InputStreamReadernem korlátozódik az adatok konzolról történő kiolvasására. Más helyekről is képes adatokat olvasni. Például egy fájlból:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

   public static void main(String[] args) throws IOException {
       InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("C:\\Users\\username\\Desktop\\testFile.txt"));
   }
}
Itt létrehozunk egy FileInputStream(egy ízű InputStream), átadjuk a fájl elérési útját, és magát a folyamot átadjuk a InputStreamReader. Most már képes lesz adatokat olvasni a fájlból (természetesen ha valóban létezik fájl az elérési úton). InputStreamReaderAdatok olvasására is az osztály metódusát használjuk read()(az adatok forrása nem számít: a konzol, egy fájl vagy máshol). Mi a különbség System.in.read()a és a között InputStreamReader.read()?\ Próbáljuk meg újra elolvasni a "魚" karaktert egy InputStreamReader. Emlékeztetlek arra, amit valójában olvasott System.in.read(): 233 173 154 10 És hogyan működik InputStreamReaderugyanez?

public class Main {

   public static void main(String[] args) throws IOException {

       InputStreamReader reader = new InputStreamReader(System.in);
       while (true) {
           int x = reader.read();
           System.out.println(x);
       }
   }
}
Konzol kimenet: 39770 10 A különbség azonnal szembetűnő. Az utolsó bájt (amely az új sort jelképezi) változatlan marad (a 10-es szám), de a "魚" karaktert egyetlen kóddá "39770" alakították át. Ezt jelenti karaktereket olvasni! Ha nem hiszed el, hogy a 39770 a "魚" betűt jelöli, akkor könnyen meggyőzheted magad :)
import java.io.IOException;

public class Main {

   public static void main(String[] args) throws IOException {

       char x = 39770;
       System.out.println(x);
   }
}
Konzol kimenet: De ha InputStreamReaderilyen nagyszerű, akkor miért van szükségünk BufferedReader? InputStreamReadertudja, hogyan kell adatokat olvasni és a bájtokat karakterekké alakítani. Mit kérhetnénk még? Miért egy másik Olvasó? :/ A válasz nagyon egyszerű: a nagyobb teljesítmény és kényelem érdekében . Kezdjük a teljesítménnyel. Adatok beolvasásakor BufferedReaderegy speciális, puffer nevű területet használ, ahol "tárolja" az olvasott karaktereket. Végül, amikor ezekre a karakterekre szükség van a programban, akkor a pufferből veszik őket, nem közvetlenül az adatforrásból (billentyűzet, fájl stb.). Ezzel rengeteg erőforrást takaríthatunk meg. Ennek megértéséhez képzeljen el egy futárt egy nagy cégnél. A futár egy irodában ül, és várja, hogy valaki csomagokat hozzon a kézbesítéshez. Minden alkalommal, amikor új csomagot kap, azonnal útnak indulhat. De sok csomag lehet napközben. Sok utat kell megtennie az iroda és a szállítási címek között. Ehelyett a futár berak egy dobozt az irodájába. Mindenki berakja a csomagját a dobozba. Most a futár nyugodtan átveheti a dobozt, és címről címre mozoghat. Ezzel sok időt takaríthat meg, mert nem kell minden alkalommal visszatérnie az irodába. Ebben a példában a doboz csak puffer, az iroda pedig adatforrás. A futárnak sokkal könnyebb egyetlen dobozból átvenni a csomagokat kézbesítéskor, mint minden alkalommal visszamenni az irodába. Megspórolja a benzint is. Hasonlóképpen, egy programban sokkal kevésbé erőforrásigényes adatot venni egy pufferből, mint minden alkalommal az adatforrásra hivatkozni. Ennek eredményekéntBufferedReader+ InputStreamReadergyorsabb, mint InputStreamReaderegyedül . A teljesítményre gondoltunk. Mi a helyzet a kényelemmel? Legfőbb előnye, hogy Bufferedreaderegyszerre nem csak egy karaktert tud olvasni (bár ezt a metódusával tudja read()), hanem egyszerre egész sorokat is! Ez a módszerrel történik readLine();

public class Main {

   public static void main(String[] args) throws IOException {

       BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
       String s = reader.readLine();
       System.out.println("We read this line from the keyboard:");
       System.out.println(s);
   }
}
Konzol kimenet: A CodeGym a legjobb webhely a Java tanuláshoz! Ezt a sort olvassuk a billentyűzetről: A CodeGym a legjobb weboldal a Java tanuláshoz! Ez különösen nagy mennyiségű adat olvasásakor hasznos. Egy-két sornyi szöveg karakterenkénti olvasása továbbra is megvalósítható. De a "Háború és béke"-ben egy-egy betűt olvasni némileg problémás lenne :)

További olvasnivalók:

Hozzászólások
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION