JavaRush /Курсы /Java Syntax Pro /Цепочки потоков

Цепочки потоков

Java Syntax Pro
15 уровень , 2 лекция
Открыта

1. Класс InputStreamReader

Еще одной интересной особенностью потоков является возможность объединять несколько потоков в цепочки. Поток может читать данные не только из источника данных, который их хранит, но из другого потока.

Это очень мощный механизм в Java, который позволил конструировать сложные сценарии чтения данных, соединяя одни потоки с другими. Выглядит такая схема примерно так:

Класс InputStreamReader

Когда программа читает данные из потока данных, он в свою очередь читает их из своего источника данных: другого потока данных или из файла, например.

При этом каждый поток данных не просто читает и отдает данные, а еще может преобразовывать их или выполнять над ними различные операции. Хорошим примером такого «промежуточного потока» данных является класс InputStreamReader.

Мы уже знаем класс, который называется FileReader, и это Reader, который читает данные из файла. А откуда читает данные класс InputStreamReader? Правильно: из потока InputStream.

Чтобы создать объект типа InputStreamReader, в него нужно передать объект типа InputStream, или его класса наследника. Пример:

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(), он в свою очередь читает из файла на диске два байта и возвращает их вам как char.

Когда вы читаете символ из объекта InputStreamReader с помощью метода read(), он в свою очередь читает два байта из переданного в него объекта FileInputStream, который в свою очередь читает данные из файла. Получается такая цепочка вызовов методов read().


2. Класс BufferedReader

Есть еще один интересный класс, который вы, скорее всего, будете часто использовать — BufferedReader. Это тоже «промежуточный поток», который читает данные из другого потока.

Класс BufferedReader, как видно из его названия, является классом-наследником от Reader и позволяет читать символы. Однако, что самое интересное, в качестве источника данных в него тоже нужно передать поток, из которого можно читать символы – поток-наследник от класса Reader.

В чем же смысл? В отличие от InputStreamReader’а, класс BufferedReader не преобразовывает байты в символы: он вообще ничего не преобразовывает. Вместо этого он буферизует данные.

Класс BufferedReader

Когда программа читает из объекта BufferedReader один символ, он читает из своего потока-источника сразу большой массив символов. И сохраняет их у себя внутри.

При чтении следующего символа из объекта BufferedReader, он просто возьмет очередной символ из своего внутреннего массива-буфера и отдаст его, не обращаясь при этом к потоку-источнику данных. И только когда все символы в буфере закончатся, он снова прочитает большой массив символов.

Еще у класса BufferedReader есть очень полезный метод — String readLine(), который позволяет читать данные из потока-источника сразу строками. С помощью этого метода можно, например, прочитать какой-то файл и вывести его содержимое на экран построчно. Пример:

Мы специально записали код в компактном формате, чтобы вы увидели, как это может быть удобно. Можно записать данный код и немного более детально.

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


Создаем объект FileReader, источник данных — файл.
Создаем объект BufferedReader, источник данных — объект FileReader;
пока в reader еще есть данные

Прочитать одну линию
Вывести линию на экран
Важный момент:

Если вы соединили несколько потоков в цепочку, метод close() достаточно вызвать только у одного из них: он вызовет его у своего источника данных и т.д., пока не дойдут до финального потока с данными.



3. Чтение с консоли

И еще один интересный факт: класс Scanner — ничто иное как входящий промежуточный поток данных, который читает их из потока System.in — тоже потока данных.

Вот два способа чтения строки с консоли:

Класс Scanner Классы BufferedReader и 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();

Наш знаменитый System.in — это ничто иное как статическая переменная in класса System. Тип ее — InputStream, а имя — in.

Так что практически с самого начала изучения Java на JavaRush вы работаете с потоками данных и строите из них цепочки. Только теперь вы будете это делать более осознанно.


Комментарии (394)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Артем Чехов Уровень 16
18 сентября 2025
К чему была задача "Пропускаем не всех"? Нам рассказали про буферы, но мы не будем использовать их в практике, нужно использовать именно Files.readAllLines(). Так еще и принципиально нельзя использовать foreach списка, а нужно использовать итерацию через for. К чему такие жесткие ограничения?
25 сентября 2025
Действительно, очень странно... Думаю перейти на курс Java 25
YoungDV Уровень 22
24 августа 2025
ЧИТАЕМ, ЗАБЫВАЕМ, ПРАКТИКУЕМСЯ, ТУПИМ, ПЕРЕЧИТАЕМ, ВСПОМИНАЕМ, ОПЯТ ЗАБЫВАЕМ . ЭТО ЧЕЛОВЕЧЕСКИЙ CPU, RAM И SSD. ГЛАВНОЕ НЕ СДАВАТЬСЯ!
NinaInfinity Уровень 21
24 июля 2025
Очень сложные задачи были в прошлой лекции, здесь все равно не особо поняла, но хотя бы лекции хватило чтобы решить задачи.
Raushan Уровень 16 Expert
23 июля 2025
Чет вообще перестал понимать, да и прошлую лекцию будто бы мимо пропустил((
25 сентября 2025
Все со временем прийдет, главное не останавливайся🤗
Anonymous #3585174 Уровень 33
15 июля 2025
Like
Сергей Сак Уровень 16
12 июля 2025

Мы уже знаем класс, который называется FileReader,
А мы уже знаем класс FileReader? По-моему в предыдущих лекциях ни слова о нем не было
4el0vek3 Уровень 36
17 июля 2025
В конце прошлой лекции были слова о нем
Anton Уровень 27
2 июня 2025
В output последней задачи почему то в ответе пишет: [a, g, i, m, o]
Evgeny Уровень 25
4 июня 2025
Потому что это HashSet — множество.
Danya Уровень 17
30 апреля 2025
первая задача кнш чуть чуть сложная а две последнии изи
Олег Сычев Уровень 12
1 мая 2025
Я наоборот, первую и третью легко сделал, а вот на второй подвис
Rasul Shidakov Уровень 20
2 апреля 2025
пздц, в первой задаче перепробовал где то 10 кодов, пока правильно понял условие задачи... написано вывод строк через одну, а я все это время думал через пробел...в итоге вся попа горит от потерянного времени
ShadyLine Уровень 30
26 марта 2025
Теория ясна и понятна вроде, а вот с практикой пока что туговатый уровень