CodeGym /Blog Java /Aleatoriu /Citirea de la tastatură: „cititori”
John Squirrels
Nivel
San Francisco

Citirea de la tastatură: „cititori”

Publicat în grup
Bună! Lecțiile și sarcinile de la Nivelul 3 v-au învățat cum să afișați lucruri pe consolă și, mergând în cealaltă direcție, cum să citiți datele de pe tastatură.
Citirea de la tastatură: „cititori” - 1
Ați învățat chiar să utilizați următorul construct complex pentru a realiza acest lucru:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Dar există o întrebare la care încă nu am răspuns.

Cum naiba funcționează asta?

În realitate, programele sunt rareori complet independente. Ei comunică cu alte programe, sisteme, internetul etc. Prin „comunicare”, înțelegem în principal „schimb de date”. Adică primesc niște date externe și trimit și date interne ale programului undeva. Exemplele de programe care fac schimb de date abundă în viața de zi cu zi. De exemplu, multe site-uri web vă permit să vă conectați folosind contul de Facebook sau Twitter în loc să vă înregistrați. În această situație, două programe (de exemplu, Twitter și site-ul web la care vă conectați) schimbă datele necesare. Rezultatul final este că v-ați conectat cu succes. Cuvântul „flux”este folosit pentru a descrie procesul de schimb de date. De unde a venit acest nume? Din experiența dumneavoastră, un „pârâu” poate fi asociat mai mult cu râurile și decât cu programarea. Nu este o întâmplare :) Un flux este, în esență, o bucată de date în mișcare. Cu alte cuvinte, în programare, nu apa curge, ci mai degrabă datele sub formă de octeți și caractere. Putem primi biți de date dintr-un flux de date și apoi să le folosim. Din nou, vom folosi analogia apă/debit: puteți scoate apă dintr-un râu pentru a face supă, a stinge focul sau a uda florile. Fluxurile vă permit să lucrați cu orice sursă de date: fie că este Internet, sistemul de fișiere al computerului sau altceva - nu are nicio diferență. Fluxurile sunt un instrument universal. Acestea permit unui program să primească date de oriunde (fluxuri de intrare) și să le trimită oriunde (fluxuri de ieșire). Sarcina lor este aceeași: să preia date dintr-un loc și să le trimită în altul. Există două tipuri de fluxuri:
  1. Fluxurile de intrare sunt folosite pentru a primi date
  2. Fluxurile de ieșire sunt pentru trimiterea datelor.
În Java, aceste fluxuri sunt implementate de clasele InputStreamși OutputStream. Dar fluxurile pot fi clasificate în alt mod. Pe lângă fluxurile de intrare și ieșire, vorbim și de fluxuri de octeți și fluxuri de caractere . Semnificația aici ar trebui să fie suficient de clară: fluxul de octeți trimite informații ca un set de octeți, în timp ce un flux de caractere le trimite ca un set de caractere. În această lecție, ne vom opri asupra fluxurilor de intrare. Voi pune un link cu informații despre fluxurile de ieșire la sfârșitul lecției. Îl poți citi pe cont propriu :) Acum aruncă o privire la acest cod:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Când parcurgeai lecțiile, nu crezi că această replică este destul de intimidantă? :) Acesta nu va fi cazul după ce vom explora modul în care funcționează. Să îndreptăm lucrurile. Vom începe de la sfârșit. System.ineste un InputStreamobiect, o instanță a clasei despre care am vorbit mai devreme. Este un flux de intrare legat de un dispozitiv de intrare de sistem (tastatura). Apropo, ești indirect familiarizat cu acest flux. La urma urmei, îl folosești frecvent „colegul” — System.out! System.outeste fluxul de ieșire al sistemului . Este folosit pentru a trimite date către consolă prin metoda preferată System.out.println(), pe care o utilizați constant :) System.outeste un flux pentru trimiterea datelor către consolă, în timp ceSystem.ineste pentru a obține date de la tastatură. Totul este simplu :) Mai mult, putem citi date de la tastatură fără această construcție uriașă. Putem scrie simplu: 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);
       }
   }
}
Clasa InputStream(rețineți, System.ineste un InputStreamobiect) are o read()metodă care vă permite să citiți datele. Există o problemă: citește octeți , nu caractere . Este plictisitor să folosești doar litere englezești, așa că hai să încercăm să citim caracterul chinezesc „魚” de la tastatură (doar copiați această literă de aici și lipiți-o pe consolă folosind ctrl + v pe PC sau Command + v pe Mac ) . Apropo, acest caracter înseamnă „un pește”. Ieșire console: 233 173 154 10 Acest simbol și multe alte chinezești ocupă 3 octeți în memoria computerului (spre deosebire de literele latine, care ocupă doar 1 octet). În acest caz, 4 octeți sunt citiți din flux: primii trei reprezintă caracterul „魚”, iar celălalt octeți reprezintă o nouă linie (Enter). În consecință, System.inîn forma sa neîmpodobită nu este o opțiune pentru noi. Oamenii (cu rare excepții!) nu știu să citească octeți. Dar InputStreamReaderclasa vine în ajutor! Să vedem ce fel de animal este acesta.

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
Trecem System.inla obiectul InputStreamReader . Numele clasei o spune! Creăm un InputStreamReaderobiect și îi transmitem un flux de intrare din care va citi datele. În acest caz...

new InputStreamReader(System.in)
... noi îi spunem, „veți citi date din fluxul de intrare al sistemului (de la tastatură)”. Dar aceasta nu este singura ei funcție! Nu numai că InputStreamReaderprimește date din flux. De asemenea, convertește fluxurile de octeți în fluxuri de caractere . Cu alte cuvinte, nu mai trebuie să convertiți datele din „unu și zero” într-un „limbaj care poate fi citit de om”. InputStreamreaderface totul pentru tine. Desigur, InputStreamReadernu se limitează la citirea datelor din consolă. Poate citi și date din alte locuri. De exemplu, dintr-un fișier:

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"));
   }
}
Aici creăm un FileInputStream(o aromă de InputStream), trecem calea fișierului și transmitem fluxul în sine către InputStreamReader. Acum va putea citi date din fișier (dacă un fișier există de fapt la cale, desigur). De asemenea, folosim metoda InputStreamReaderclasei read()pentru a citi datele (sursa datelor nu contează: consola, un fișier sau în altă parte). Care este diferența dintre System.in.read()și InputStreamReader.read()?\ Să încercăm din nou să citim caracterul „魚” cu un InputStreamReader. Vă reamintesc ceea ce a fost citit de fapt de System.in.read(): 233 173 154 10 Și cum funcționează InputStreamReaderacelași lucru?

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);
       }
   }
}
Ieșire console: 39770 10 Diferența este imediat evidentă. Ultimul octet (reprezentând noua linie) rămâne neschimbat (numărul 10), dar caracterul „魚” a fost convertit într-un singur cod „39770”. Asta înseamnă să citești personaje! Dacă nu crezi că 39770 reprezintă litera „魚”, e ușor să te convingi :)
import java.io.IOException;

public class Main {

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

       char x = 39770;
       System.out.println(x);
   }
}
Ieșire din consolă: Dar dacă InputStreamReadereste atât de grozav, de ce avem și noi nevoie BufferedReader? InputStreamReaderștie să citească date și să convertească octeții în caractere. Ce am putea cere mai mult? De ce alt cititor? :/ Răspunsul este foarte simplu: pentru mai multă performanță și confort . Să începem cu performanța. Când BufferedReadercitește datele, folosește o zonă specială numită buffer, unde „stochează” caracterele pe care le citește. În cele din urmă, atunci când aceste caractere sunt necesare în program, ele vor fi preluate din buffer, nu direct din sursa de date (tastatură, fișier etc.). Acest lucru economisește o mulțime de resurse. Pentru a înțelege cum funcționează, imaginați-vă un curier într-o companie mare. Curierul stă într-un birou, așteptând ca cineva să aducă pachete pentru livrare. De fiecare dată când primește un pachet nou, poate ieși imediat la drum. Dar ar putea fi o mulțime de pachete în timpul zilei. Ar trebui să facă o mulțime de călătorii între birou și adresele de livrare. În schimb, curierul pune o cutie în biroul lui. Toată lumea își pune pachetele în cutie. Acum, curierul poate lua cu calm cutia si se poate muta de la adresa la adresa. Acest lucru economisește mult timp, pentru că nu trebuie să se întoarcă la birou de fiecare dată. În acest exemplu, caseta este doar un buffer, iar biroul este o sursă de date. Curierului îi este mult mai ușor să ia pachete dintr-o singură cutie atunci când face livrări decât să se întoarcă la birou de fiecare dată. Va economisi și benzină. În mod similar, într-un program este mult mai puțin consumator de resurse pentru a prelua date dintr-un buffer decât pentru a face referire la sursa de date de fiecare dată. Ca urmare,BufferedReader+ InputStreamReadereste mai rapid decât InputStreamReadersingur . Ne-am gândit la performanță. Ce zici de comoditate? Principalul avantaj este că Bufferedreaderpoate citi datele nu doar un caracter la un moment dat (deși poate face acest lucru cu read()metoda sa), ci și linii întregi la un moment dat! Acest lucru se face folosind readLine()metoda;

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);
   }
}
Ieșire din consolă: CodeGym este cel mai bun site web pentru a învăța Java! Citim această linie de la tastatură: CodeGym este cel mai bun site web pentru a învăța Java! Acest lucru este util în special atunci când citiți cantități mari de date. Citirea unuia sau a două rânduri de text caracter cu caracter este încă fezabilă. Dar citirea în „Război și pace” câte o scrisoare ar fi oarecum problematică :)

Mai multe lecturi:

Comentarii
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION