1. InputStreamReaderclasa

O altă caracteristică interesantă a fluxurilor este că puteți combina mai multe fluxuri împreună în lanțuri . Un flux poate citi date nu numai din sursa sa internă de date, ci și din alt flux .

Acesta este un mecanism foarte puternic în Java, care face posibilă crearea unor scenarii complexe de citire a datelor prin conectarea unui flux la altul. O astfel de schemă arată astfel:

Clasa InputStreamReader

Când un program citește date dintr-un flux de date, fluxul de date citește la rândul său datele din sursa sa de date, care este un alt flux de date sau un fișier, de exemplu.

În plus, fiecare flux de date nu numai că citește și emite date, dar poate și să le transforme sau să efectueze diverse operații asupra acestuia. Un bun exemplu de astfel de „flux intermediar” este InputStreamReaderclasa.

Știm deja o clasă numită FileReader- este o clasă Readercare citește date dintr-un fișier. Și InputStreamReaderde unde își iau datele? Așa este — dintr-un InputStream.

Când creați un InputStreamReaderobiect, trebuie să treceți un InputStreamobiect sau una dintre clasele sale descendente. Exemplu:

String src = "c:\\projects\\log.txt";
FileInputStream input = new FileInputStream(src);
InputStreamReader reader = new InputStreamReader(input);

Clasa InputStreamReaderare toate metodele pe care le Readerare clasa și funcționează exact în același mod.

Principala diferență dintre InputStreamReaderclasă și, să zicem, FileReadereste de unde citesc datele. FileReadercitește date dintr-un fișier (duh — de aceea se numește FileReader), dar InputStreamReadercitește date dintr-un fișier InputStream.

Când citiți un caracter dintr-un FileReaderobiect folosind read()metoda, acesta citește, la rândul său, doi octeți din fișierul de pe disc și îi returnează ca chars.

Când citiți un caracter dintr-un InputStreamReaderobiect folosind read()metoda, acesta citește, la rândul său, doi octeți din FileInputStreamobiectul care i-a fost transmis, care la rândul său citește datele din fișier. Rezultatul este un lanț de apeluri la read()metode.


2. BufferedReaderclasa

O altă clasă interesantă pe care probabil o vei folosi foarte mult este BufferedReader. Acesta este, de asemenea, un „flux intermediar” care citește date dintr-un alt flux.

După cum sugerează și numele, BufferedReaderclasa este o subclasă Readerși vă permite să citiți caractere . Dar ceea ce este cel mai interesant este că trebuie să îi treci și o sursă de date sub forma unui flux din care pot fi citite caracterele , adică un flux care moștenește Readerclasa.

Care e ideea? Spre deosebire de InputStreamReader, BufferedReaderclasa nu convertește octeții în caractere: nu convertește absolut nimic. În schimb, pune în tampon datele .

Când un program citește un singur caracter dintr-un BufferedReaderobiect, obiectul citește o gamă largă de caractere din fluxul sursă dintr-o dată. Și le stochează intern.

Când următorul caracter este citit din BufferedReaderobiect, pur și simplu preia următorul caracter din matricea sa de buffer intern și îl returnează fără a accesa sursa de date. Numai când toate caracterele din buffer sunt epuizate, se citește într-o altă serie mare de caractere.

Clasa BufferedReaderare, de asemenea, o metodă foarte utilă — String readLine(), care vă permite să citiți șiruri întregi de date din fluxul sursă dintr-o dată. Puteți folosi această metodă pentru, de exemplu, să citiți un fișier și să afișați conținutul acestuia pe ecran, linie cu linie. Exemplu:

Am scris în mod special un cod compact pentru a ilustra cât de convenabil poate fi acest lucru. Acest cod ar putea fi scris și cu puțin mai multe detalii.

String src = "c:\\projects\\log.txt";

try(FileReader in = new FileReader(src);
BufferedReader reader = new BufferedReader(in))
{
   while (reader.ready())
   {
      String line = reader.readLine();
      System.out.println(line);
   }
}
Creați un FileReaderobiect. Sursa de date este un fișier.
Creați un BufferedReaderobiect. Sursa de date este un FileReader.
Atâta timp cât mai există date în cititor
Citiți o linie
Afișați linia
Un punct important:

Dacă înlănțuiți mai multe fluxuri, atunci close()metoda trebuie apelată doar pe unul dintre ele. Fluxul respectiv va apela metoda pe sursa sa de date și așa mai departe, până când close()este apelat pe fluxul de date final.



3. Citirea de pe consolă

Și încă un fapt interesant: Scannerclasa nu este altceva decât un flux de intrare intermediar care citește date din System.in, care este și un flux de date.

Iată două moduri de a citi o linie din consolă:

Clasa de scaner Clasele BufferedReader și BufferedWriter
InputStream stream = System.in;
Scanner console = new Scanner(stream);
String line = console.nextLine();
InputStream stream = System.in;
InputStreamReader reader = new InputStreamReader(stream);
BufferedReader buff = new BufferedReader(reader);
String line = buff.readLine();

Prietenul nostru nu este altceva decât o variabilă statică a clasei. Este un al cărui nume este .System.ininSystemInputStreamin

Deci, aproape de la începutul studiilor tale Java pe CodeGym, ai lucrat cu fluxuri de date și ai construit lanțuri din ele. Dar acum o vei face mai conștient.