1 klasaInputStreamReader

Kolejną interesującą cechą wątków jest możliwość łączenia wielu wątków w łańcuchy. Wątek może odczytywać dane nie tylko ze źródła danych, które je przechowuje, ale także z innego wątku.

Jest to bardzo potężny mechanizm w Javie, który umożliwił konstruowanie złożonych scenariuszy odczytu danych poprzez łączenie jednego strumienia z drugim. Taki schemat wygląda następująco:

Klasa InputStreamReader

Gdy program odczytuje dane ze strumienia danych, z kolei odczytuje je ze swojego źródła danych: na przykład innego strumienia danych lub pliku.

Jednocześnie każdy strumień danych nie tylko odczytuje i przekazuje dane, ale także może je przekształcać lub wykonywać na nich różne operacje. Dobrym przykładem takiego „pośredniego przepływu” danych jest plik InputStreamReader.

Znamy już klasę o nazwie FileReader, a jest nią Reader, która odczytuje dane z pliku. Skąd klasa odczytuje dane InputStreamReader? Zgadza się: ze strumienia InputStream.

Aby utworzyć obiekt typu InputStreamReader, musisz przekazać do niego obiekt typu lub jego następcę klasy InputStream. Przykład:

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

Klasa InputStreamReaderma wszystkie metody, które ma klasa Reader, i działają one dokładnie w ten sam sposób.

Główna różnica między klasami InputStreamReaderi, na przykład, FileReaderpolega na tym, skąd odczytują dane. FileReaderodczytuje dane z pliku (dlatego nazywa się FileReader), ale InputStreamReaderodczytuje dane ze strumienia InputStream.

Gdy odczytujesz znak z obiektu FileReadertą metodą read(), on z kolei odczytuje dwa bajty z pliku na dysku i zwraca je jako char.

Gdy odczytujesz znak z obiektu InputStreamReaderza pomocą metody read(), obiekt z kolei odczytuje dwa bajty z przekazanego mu obiektu FileInputStream, który z kolei odczytuje dane z pliku. Okazuje się taki łańcuch wywołań metod read().


2. KlasaBufferedReader

Jest jeszcze jedna interesująca klasa, której prawdopodobnie będziesz często używać — BufferedReader. Jest to również „wątek pośredni”, który odczytuje dane z innego wątku.

Klasa BufferedReader, jak sama nazwa wskazuje, jest klasą, która dziedziczy po znakach Readeri umożliwia ich odczytywanie . Jednak co najciekawsze, jako źródło danych trzeba do niego również przekazać strumień, z którego można odczytać znaki – strumień, który dziedziczy po klasie Reader.

O co chodzi? W przeciwieństwie do InputStreamReader„a, klasa BufferedReadernie konwertuje bajtów na znaki: w ogóle niczego nie konwertuje. Zamiast tego buforuje dane .

Klasa BufferedReader

Gdy program odczytuje BufferedReaderpojedynczy znak z obiektu, jednocześnie odczytuje dużą tablicę znaków ze swojego strumienia źródłowego. I trzyma je w środku.

Podczas odczytywania następnego znaku z obiektu BufferedReaderpo prostu pobiera następny znak z wewnętrznej tablicy buforów i zwraca go bez odwoływania się do strumienia źródła danych. I tylko wtedy, gdy wszystkie znaki w buforze się skończą, ponownie odczyta dużą tablicę znaków.

Klasa BufferedReaderposiada również bardzo przydatną metodę - String readLine(), która pozwala odczytywać dane ze strumienia źródłowego od razu w liniach. Za pomocą tej metody można na przykład odczytać plik i wyświetlić jego zawartość na ekranie linia po linii. Przykład:

Celowo napisaliśmy kod w zwartym formacie, abyś mógł zobaczyć, jakie to może być wygodne. Możesz napisać ten kod bardziej szczegółowo.

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);
   }
}


Tworzymy obiekt FileReader, źródłem danych jest plik.
Tworzymy obiekt BufferedReader, źródłem danych jest obiekt FileReader;
dopóki readerdane są nadal dostępne

Przeczytaj jedną linię
Wyświetl linię na ekranie
Ważny punkt:

Jeśli połączyłeś kilka strumieni w łańcuch, wystarczy wywołać metodę close()tylko na jednym z nich: wywoła ją na swoim źródle danych i tak dalej, aż dotrze do końcowego strumienia danych.



3. Odczyt z konsoli

I jeszcze jeden ciekawy fakt: klasa Scannerto nic innego jak przychodzący pośredni strumień danych, który odczytuje je ze strumienia System.in- także strumienia danych.

Oto dwa sposoby odczytania wiersza z konsoli:

Klasa skanera klasy BufferedReader i InputStreamReader
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();

Nasza słynna zmienna to nic innego jak statyczna zmienna klasowa . Jego typ to , a jego nazwa to .System.ininSystemInputStreamin

Tak więc prawie od samego początku nauki Javy na CodeGym pracujesz ze strumieniami danych i budujesz z nich łańcuchy. Dopiero teraz zrobisz to bardziej świadomie.