JavaRush/Курси/Java Syntax Zero/Ланцюжки потоків

Ланцюжки потоків

Відкрита

1. Клас InputStreamReader

Ще однією цікавою особливістю потоків є можливість об'єднувати кілька потоків у ланцюжки. Потік може читати дані не тільки із джерела даних, в якому вони зберігаються, але також з іншого потоку.

Це дуже потужний механізм у Java, який дав змогу конструювати складні сценарії читання даних, поєднуючи різні потоки. Ця схема має приблизно такий вигляд:

Коли програма читає дані з потоку даних, він своєю чергою читає їх зі свого джерела даних: з іншого потоку даних або, наприклад, із файлу.

Кожен потік даних не просто читає та віддає дані, а водночас може перетворювати їх або виконувати з ними різні операції. Наочним прикладом такого «проміжного потоку» даних є клас 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 має дуже корисний метод 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() досить викликати тільки у одного з них: він викличе його у свого джерела даних і т. д., доки не буде закрито останній потік даних.


16
Задача
Java Syntax Zero,  16 рівень3 лекція
Недоступна
Пропускаємо не всіх
Напиши програму, яка зчитує з консолі ім'я текстового файлу, далі читає рядки з цього файлу (використай метод readAllLines(Path) класу Files) і виводить їх на екран через один, починаючи з першого.

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. А відтепер ви зможете це робити більш осмислено.


16
Задача
Java Syntax Zero,  16 рівень3 лекція
Недоступна
Читаємо з консолі
Програма зчитує з консолі рядок і виводить його на екран, чергуючи регістр символів: перший символ — у нижньому регістрі, другий — у верхньому, третій — у нижньому і т. д. Не змінюючи функцій програми, перепиши код із використанням BufferedReader для читання з консолі.
16
Задача
Java Syntax Zero,  16 рівень3 лекція
Недоступна
Ще раз читаємо з консолі
Програма зчитує з консолі рядок і виводить перелік літер, з яких складається введений рядок. Не змінюючи функцій програми, перепиши код із використанням Scanner для читання з консолі.
Коментарі (17)
  • популярні
  • нові
  • старі
Щоб залишити коментар, потрібно ввійти в систему
Роман
Рівень 28
8 червня 2025, 13:43
Получается класс System наследует класс InputStream? - ("Виявляється, наш знаменитий System.in — це статична змінна in класу System. Її тип — InputStream, а ім'я — in.")
Alexander Kisil Full Stack Developer в rental24h
27 жовтня 2024, 21:43
В попередній темі вчились користуватись try-catch, а виявилось що тут вже ними користуватись не можна ("Пропускаємо не всіх"), бо не пройде провірку. Можливо у розділі задачі, де написано чим не можна користуватись, також додавати "Не можна використовувати, те що ви проходили до цього". ((
IronMan57
Рівень 1
4 січня 2025, 19:25
Наскільки зрозумів, в задачах до цієї та попередньої лекції потрібно використовувати не просто try-catch, а try-with-resources. Хоча, іноді не вгадаєш, що цьому валідатору не подобається. В першій задачі до цієї лекції ("Пропускаємо не всіх"), дійсно валідатор пропускав не всіх, наприклад моє рішення, в якому була стрічка-запрошення:
System.out.println("Enter the name of the source file: ");
Як тільки її закоментував - рішення було прийняте.
Viacheslav B. System Administrator
27 березня 2024, 11:34
ця лекція більш менш була зрозуміла, задачі не викликали багато запитань, а ось з попередньої були проблеми з вирішуванням задач. мабуть за мало інформації або практики...
Василь trainee в Kindgeek
27 вересня 2023, 12:23
До опису класів Scanner і BufferedReader додали б коротку форму запису, а саме:
Scanner scanner = new Scanner(System.in);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
або б додавали лінки де можна почитати ще, якщо самі тему розкрити не можете.
Pavlo Kezin
Рівень 23
22 вересня 2023, 08:18
Просто напишу. Лекцією не задоволений.
Богдан Штурмовик в 3ОШБр
26 серпня 2023, 19:47
чудова лекція! все зрозуміло.🤓😉
PAMPERS
Рівень 26
13 серпня 2023, 09:01
Я не зрозумів навіщо накидувати ще додатково теми, якщо задач мало на таку важку як я вважаю тему. Типу для засвоєння знань задач і так мало, так для вирішення задач які є треба додатково самим щось читати, все просто забувається.
Роман
Рівень 94
Expert
16 червня 2023, 18:39
Цілком підттримаю всі попередні коментарі, викладання не зрозуміле, деякі задачі можна вирішити трішки інакше але цілком в рамках данної теми, але вони не проходять, іноді просто смішно...
les_yeux_blancs QA Automation Engineer
29 квітня 2023, 11:52
Дуже туго подано, треба більш детально й більше прикладів, я зрозумів лише тому, що й так знав, як воно працює
Ivan Lebid'
Рівень 108
Expert
28 квітня 2023, 21:07
фух щось з кожним рівнем якось все більше не вкладається інфа в голові(