1. Fluxuri de date
Rareori un program există ca o insulă în sine. De obicei, programele interacționează cumva cu „lumea exterioară”. Acest lucru se poate întâmpla prin citirea datelor de la tastatură, trimiterea de mesaje, descărcarea paginilor de pe Internet sau, dimpotrivă, încărcarea fișierelor pe un server la distanță.
Ne putem referi la toate aceste comportamente într-un singur cuvânt: schimb de date între program și lumea exterioară. Stai, acesta nu este doar un cuvânt.
Desigur, schimbul de date în sine poate fi împărțit în două părți: primirea datelor și trimiterea datelor. De exemplu, citiți date de la tastatură folosind un Scanner
obiect - acesta este primirea datelor. Și afișați datele pe ecran folosind o System.out.println()
comandă - aceasta este trimiterea datelor.
În programare, termenul „flux” este folosit pentru a descrie schimbul de date. De unde a venit acel termen?
În viața reală, poți avea un curent de apă sau un curent de conștiință. În programare, avem fluxuri de date .
Fluxurile sunt un instrument versatil. Acestea permit programului să primească date de oriunde (fluxuri de intrare) și să trimită date oriunde (fluxuri de ieșire). Astfel, există două tipuri:
- Un flux de intrare este pentru primirea datelor
- Un flux de ieșire este pentru trimiterea datelor
Pentru a face fluxurile „tangibile”, creatorii Java au scris două clase: InputStream
și OutputStream
.
Clasa InputStream
are o read()
metodă care vă permite să citiți datele din ea. Și OutputStream
clasa are o write()
metodă care vă permite să scrieți date în ea. Au și alte metode, dar mai multe despre asta mai târziu.
Fluxuri de octeți
Despre ce fel de date vorbim? Ce format are? Cu alte cuvinte, ce tipuri de date acceptă aceste clase?
Acestea sunt clase generice, deci acceptă cel mai comun tip de date - byte
. Un OutputStream
poate scrie octeți (și matrice de octeți), iar un InputStream
obiect poate citi octeți (sau matrice de octeți). Asta este — nu acceptă alte tipuri de date.
Drept urmare, aceste fluxuri sunt numite și fluxuri de octeți .
O caracteristică a fluxurilor este că datele lor pot fi citite (sau scrise) numai secvenţial. Nu puteți citi date din mijlocul unui flux fără să citiți toate datele care vin înaintea acestuia.
Așa funcționează citirea datelor de la tastatură prin Scanner
clasă: citiți datele de la tastatură secvenţial, rând cu linie. Citim un rând, apoi următorul rând, apoi următorul rând și așa mai departe. În mod potrivit, metoda de citire a liniilor se numește nextLine()
.
Scrierea datelor într-un OutputStream
are loc, de asemenea, secvenţial. Un bun exemplu în acest sens este ieșirea din consolă. Ieși o linie, urmată de alta și alta. Aceasta este ieșire secvențială. Nu puteți scoate prima linie, apoi a zecea și apoi a doua. Toate datele sunt scrise într-un flux de ieșire numai secvenţial.
Fluxuri de caractere
Ați aflat recent că șirurile de caractere sunt al doilea cel mai popular tip de date și, într-adevăr, sunt. O mulțime de informații sunt transmise sub formă de caractere și șiruri întregi. Un computer excelează la trimiterea și primirea totul ca octeți, dar oamenii nu sunt atât de perfecți.
Luând în considerare acest fapt, programatorii Java au mai scris două clase: Reader
și Writer
. Clasa Reader
este analogă cu InputStream
clasa, dar read()
metoda sa citește nu octeți, ci caractere ( char
). Clasa Writer
corespunde clasei OutputStream
. Și la fel ca și Reader
clasa, funcționează cu caractere ( char
), nu cu octeți.
Dacă comparăm aceste patru clase, obținem următoarea imagine:
octeți (octeți) | Caractere (caracter) | |
---|---|---|
Citirea datelor |
|
|
Scrierea datelor |
|
|
Aplicație practică
Clasele InputStream
, OutputStream
, Reader
și Writer
în sine nu sunt folosite direct de nimeni, deoarece nu sunt asociate cu niciun obiect concret din care să poată fi citite date (sau în care să poată fi scrise date). Dar aceste patru clase au o mulțime de clase descendente care pot face multe.
2. InputStream
clasa
Clasa InputStream
este interesantă pentru că este clasa părinte pentru sute de clase descendente. Nu are date proprii, dar are metode pe care toate clasele sale derivate le moștenesc.
În general, este rar ca obiectele de flux să stocheze date intern. Un flux este un instrument de citire/scriere de date, dar nu de stocare. Acestea fiind spuse, există și excepții.
Metode ale InputStream
clasei și ale tuturor claselor sale descendente:
Metode | Descriere |
---|---|
|
Citește un octet din flux |
|
Citește o serie de octeți din flux |
|
Citește toți octeții din flux |
|
Omite n octeți în flux (i citește și îi renunță) |
|
Verifică câți octeți au mai rămas în flux |
|
Închide fluxul |
Să trecem pe scurt prin aceste metode:
read()
metodă
Metoda read()
citește un octet din flux și îl returnează. S-ar putea să fii confuz de int
tipul de returnare. Acest tip a fost ales deoarece int
este tipul întreg standard. Primii trei octeți ai int
vor fi zero.
read(byte[] buffer)
metodă
Aceasta este a doua variantă a read()
metodei. Vă permite să citiți o matrice de octeți InputStream
dintr-o dată. Matricea care va stoca octeții trebuie să fie transmisă ca argument. Metoda returnează un număr - numărul de octeți citiți efectiv.
Să presupunem că aveți un buffer de 10 kiloocteți și citiți date dintr-un fișier folosind FileInputStream
clasa. Dacă fișierul conține doar 2 kiloocteți, toate datele vor fi încărcate în matricea tampon, iar metoda va returna numărul 2048 (2 kiloocteți).
readAllBytes()
metodă
O metoda foarte buna. Pur și simplu citește toate datele din InputStream
până când se epuizează și le returnează ca o matrice de un singur octet. Acest lucru este foarte util pentru citirea fișierelor mici. Este posibil ca fișierele mari să nu încapă fizic în memorie, iar metoda va crea o excepție.
skip(long n)
metodă
Această metodă vă permite să omiteți primii n octeți din InputStream
obiect. Deoarece datele sunt citite strict secvențial, această metodă citește pur și simplu primii n octeți din flux și îi aruncă.
Returnează numărul de octeți care au fost săriți efectiv (în cazul în care fluxul s-a încheiat înainte ca n
octeții să fie săriți).
int available()
metodă
Metoda returnează numărul de octeți care au mai rămas în flux
void close()
metodă
Metoda close()
închide fluxul de date și eliberează resursele externe asociate acestuia. Odată ce un flux este închis, nu mai pot fi citite date din acesta.
Să scriem un exemplu de program care copiază un fișier foarte mare. Nu putem folosi readAllBytes()
metoda pentru a citi întregul fișier în memorie. Exemplu:
Cod | Notă |
---|---|
|
InputStream pentru citirea din fișier OutputStream pentru scriere în fișier Buffer în care vom citi datele Atâta timp cât există date în flux Citiți date în buffer Scrieți datele din buffer în al doilea flux |
În acest exemplu, am folosit două clase: FileInputStream
este un descendent al lui InputStream
pentru citirea datelor dintr-un fișier și FileOutputStream
este un descendent al lui OutputStream
pentru scrierea datelor într-un fișier. Despre clasa a doua vom vorbi puțin mai târziu.
Un alt punct interesant aici este real
variabila. Când ultimul bloc de date este citit dintr-un fișier, acesta ar putea avea cu ușurință mai puțin de 64 KB de date. În consecință, trebuie să scoatem nu întregul buffer, ci doar o parte din acesta - primii real
octeți. Este exact ceea ce se întâmplă în write()
metodă.
3. Reader
clasa
Clasa Reader
este un analog complet al InputStream
clasei. Singura diferență este că funcționează cu caractere ( char
), nu cu octeți. La fel ca InputStream
clasa, Reader
clasa nu este folosită nicăieri singură: este clasa părinte pentru sute de clase descendente și definește metode comune pentru toate.
Metode ale Reader
clasei (și toate clasele sale descendente):
Metode | Descriere |
---|---|
|
Citește unul char din flux |
|
Citește o char matrice din flux |
|
Omite n chars în flux (le citește și le elimină) |
|
Verifică dacă a mai rămas ceva în flux |
|
Închide fluxul |
Metodele sunt foarte asemănătoare cu cele ale InputStream
clasei, deși există mici diferențe.
int read()
metodă
Această metodă citește unul char
din flux și îl returnează. Tipul char
se lărgește la un int
, dar primii doi octeți ai rezultatului sunt întotdeauna zero.
int read(char[] buffer)
metodă
Aceasta este a doua variantă a read()
metodei. Vă permite să citiți o matrice de caractere Reader
dintr-o dată. Matricea care va stoca caracterele trebuie transmisă ca argument. Metoda returnează un număr — numărul de caractere citite efectiv.
skip(long n)
metodă
Această metodă vă permite să săriți peste primele n caractere din Reader
obiect. Funcționează exact la fel ca metoda analogă a InputStream
clasei. Returnează numărul de caractere care au fost de fapt sărit.
boolean ready()
metodă
Returnează true
dacă există octeți necitiți în flux.
void close()
metodă
Metoda close()
închide fluxul de date și eliberează resursele externe asociate acestuia. Odată ce un flux este închis, nu mai pot fi citite date din acesta.
Pentru comparație, să scriem un program care copiază un fișier text:
Cod | Notă |
---|---|
|
Reader pentru citirea dintr-un fișier Writer pentru scrierea într-un fișier Buffer în care vom citi datele Atâta timp cât există date în flux Citiți date într-un buffer Scrieți datele din buffer în al doilea flux |
GO TO FULL VERSION