1. InputStreamReaderклас
Друга интересна характеристика на потоците е, че можете да комбинирате множество потоци заедно във вериги . Потокът може да чете данни не само от своя вътрешен източник на данни, но и от друг поток .
Това е много мощен механизъм в Java, който прави възможно създаването на сложни сценарии за четене на данни чрез свързване на един поток към друг. Такава схема изглежда така:

Когато една програма чете данни от поток от данни, потокът от данни на свой ред чете данните от своя източник на данни, който е друг поток от данни or файл, например.
Нещо повече, всеки поток от данни не само чете и издава данни, но също така може да ги трансформира or да извършва различни операции върху тях. Добър пример за такъв "междинен поток" е класът InputStreamReader.
Вече знаем клас, наречен FileReader— това е Reader, който чете данни от файл. И откъде InputStreamReaderима данните? Точно така — от InputStream.
Когато създавате InputStreamReaderобект, трябва да предадете InputStreamобект or един от неговите наследствени класове. Пример:
String src = "c:\\projects\\log.txt";
FileInputStream input = new FileInputStream(src);
InputStreamReader reader = new InputStreamReader(input);
Класът InputStreamReaderима всички методи, които Readerкласът има, и те работят по абсолютно същия начин.
Основната разлика между InputStreamReaderкласа и, да речем, FileReaderе откъде четат данни. FileReaderчете данни от файл (да — затова се нарича FileReader), но InputStreamReaderчете данни от InputStream.
Когато четете знак от FileReaderобект с помощта на read()метода, той от своя страна чете два byteа от file на диска и ги връща като chars.
Когато четете символ от InputStreamReaderобект с помощта на read()метода, той от своя страна чете два byteа от FileInputStreamобекта, който му е предаден, което от своя страна чете данни от file. Резултатът е верига от извиквания на read()методи.
2. BufferedReaderклас
Друг интересен клас, който вероятно ще използвате често, е BufferedReader. Това също е "междинен поток", който чете данни от друг поток.
Както подсказва името му, BufferedReaderкласът е подклас на Readerи ви позволява да четете знаци . Но най-интересното е, че вие също трябва да му предадете източник на данни под формата на поток, от който могат да се четат символи , т.е. поток, който наследява Readerкласа.
Какъв е смисълът? За разлика от InputStreamReader, BufferedReaderкласът не преобразува byteове в знаци: той изобщо не преобразува нищо. Вместо това буферира данните .

Когато една програма чете един знак от BufferedReaderобект, обектът чете наведнъж голям набор от знаци от своя изходен поток. И ги съхранява вътрешно.
Когато следващият знак бъде прочетен от BufferedReaderобекта, той просто грабва следващия знак от своя вътрешен буферен масив и го връща без достъп до източника на данни. Само когато всички символи в буфера са изразходвани, той чете друг голям масив от знаци.
Класът BufferedReaderсъщо има много полезен метод — String readLine(), който ви позволява да четете цели низове от данни от изходния поток наведнъж. Можете да използвате този метод, да речем, да прочетете файл и да покажете съдържанието му на екрана ред по ред. Пример:
Специално написахме компактен code, за да илюстрираме колко удобно може да бъде това. Този code също може да бъде написан с малко повече подробности.
|
Създайте FileReaderобект. Източникът на данни е файл. Създайте BufferedReaderобект. Източникът на данни е FileReader. Докато все още има данни в четеца Прочетете един ред Покажете реда |
Ако свържете заедно няколко потока, тогава close()методът трябва да бъде извикан само на един от тях. Този поток ще извика метода на неговия източник на данни и така нататък, докато не close()бъде извикан на последния поток от данни.
3. Четене от конзолата
И още един интересен факт: Scannerкласът не е нищо повече от междинен входен поток, който чете данни от System.in, който също е поток от данни.
Ето два начина за четене на ред от конзолата:
| Клас скенер | Класове BufferedReader и BufferedWriter |
|---|---|
|
|
Нашият приятел не е нищо повече от статична променлива на класа. Това е човек , чието име е .System.ininSystemInputStreamin
Така че почти от самото начало на вашето обучение по Java в CodeGym, вие работите с потоци от данни и изграждате вериги от тях. Но сега ще го направите по-съзнателно.
GO TO FULL VERSION