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.in
in
System
InputStream
in
Така че почти от самото начало на вашето обучение по Java в CodeGym, вие работите с потоци от данни и изграждате вериги от тях. Но сега ще го направите по-съзнателно.
GO TO FULL VERSION