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 Scannerobiect - 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 InputStreamare o read()metodă care vă permite să citiți datele din ea. Și OutputStreamclasa 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 OutputStreampoate scrie octeți (și matrice de octeți), iar un InputStreamobiect 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 Scannerclasă: 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 OutputStreamare 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 Readereste analogă cu InputStreamclasa, dar read()metoda sa citește nu octeți, ci caractere ( char). Clasa Writercorespunde clasei OutputStream. Și la fel ca și Readerclasa, 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. InputStreamclasa
Clasa InputStreameste 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 InputStreamclasei ș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 nocteț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 inttipul de returnare. Acest tip a fost ales deoarece inteste tipul întreg standard. Primii trei octeți ai intvor fi zero.
read(byte[] buffer)metodă
Aceasta este a doua variantă a read()metodei. Vă permite să citiți o matrice de octeți InputStreamdintr-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 FileInputStreamclasa. 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 InputStreampâ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 InputStreamobiect. 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 nocteț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ă |
|---|---|
|
InputStreampentru citirea din fișier OutputStreampentru 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: FileInputStreameste un descendent al lui InputStreampentru citirea datelor dintr-un fișier și FileOutputStreameste un descendent al lui OutputStreampentru scrierea datelor într-un fișier. Despre clasa a doua vom vorbi puțin mai târziu.
Un alt punct interesant aici este realvariabila. 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 realocteți. Este exact ceea ce se întâmplă în write()metodă.
3. Readerclasa
Clasa Readereste un analog complet al InputStreamclasei. Singura diferență este că funcționează cu caractere ( char), nu cu octeți. La fel ca InputStreamclasa, Readerclasa nu este folosită nicăieri singură: este clasa părinte pentru sute de clase descendente și definește metode comune pentru toate.
Metode ale Readerclasei (și toate clasele sale descendente):
| Metode | Descriere |
|---|---|
|
Citește unul chardin flux |
|
Citește o charmatrice 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 InputStreamclasei, deși există mici diferențe.
int read()metodă
Această metodă citește unul chardin flux și îl returnează. Tipul charse 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 Readerdintr-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 Readerobiect. Funcționează exact la fel ca metoda analogă a InputStreamclasei. Returnează numărul de caractere care au fost de fapt sărit.
boolean ready()metodă
Returnează truedacă 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ă |
|---|---|
|
Readerpentru citirea dintr-un fișier Writerpentru 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