JavaRush /Курсы /Java Core /Пишем свой поток — обертку на System.in

Пишем свой поток — обертку на System.in

Java Core
8 уровень , 7 лекция
Открыта

— Привет, Амиго! Сегодня мы будем заниматься очень интересной работой – подменой потока ввода – System.in.

System.in – это простая статическая переменная типа InputStream, но присвоить ей новое значение просто так нельзя. Зато можно воспользоваться методом System.setIn().

Для начала нам нужно создать буфер, потом положить в него какие-то значения. Затем завернуть в класс, который умеет из этого буфера читать данные по протоколу InputStream.

Вот как это выглядит:

Код
public static void main(String[] args) throws IOException {
    //кладем данные в строку
    StringBuilder sb = new StringBuilder();
    sb.append("Lena").append('\n');
    sb.append("Olya").append('\n');
    sb.append("Anya").append('\n');
    String data = sb.toString();

    //Оборачиваем строку в класс ByteArrayInputStream
    InputStream is = new ByteArrayInputStream(data.getBytes());

    //подменяем in
     System.setIn(is);

    //вызываем обычный метод, который не подозревает о наших манипуляциях
    readAndPrintLine();
}

public static void readAndPrintLine() throws IOException {
    InputStreamReader isr = new InputStreamReader(System.in);
    BufferedReader reader = new BufferedReader(isr);

    while (true) {
        String line = reader.readLine();
        if (line == null) break;
        System.out.println(line);
    }
    reader.close();
    isr.close();
}

— Билаабо! Это самый интересный пример из всего, что я видел. Я и не знал, что так можно делать. Спасибо.

— Не за что, друг Амиго.

Комментарии (325)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Anonymous #3585174 Уровень 33
3 сентября 2025
Like
8 февраля 2025
А как вернуть в in тот поток, что был изначально? Т.е. чтобы опять было чтение с клавиатуры? Передать null в System.setIn()? В классе System значение поля in == null.
Денис Кокшаров Уровень 32
10 марта 2025
простой и быстрый ответ на твой вопрос без тонкостей: InputStream originalIn = System.in; сохранить в переменную оригинальный поток, чтобы потом его "восстановить", когда потребуется через System.setIn(originalIn) почему так, коротко, потому что такие вопросы лучше сразу задавать в чат бот. но в целом вопрос хороший, лучше его задать и сразу же ответить в комментах, для других юзеров
Артём Сёмкин Уровень 47
8 января 2025
Выглядит, как знатный прикол на 1ое апреля😅
NikitaMorozka Уровень 38
9 декабря 2024
Удалите слово "протокол", а то стыдно
NikitaMorozka Уровень 38
9 декабря 2024
Мне одному показалось, что вся статейка, это масса жизнидеятельности собаки ?
Danя Уровень 30
10 декабря 2024
и ты мне говоришь что я дед?)
{Java_Shark} Уровень 36
26 ноября 2024
++
Денис Кокшаров Уровень 32
10 марта 2025
++Java_Shark
Mabelod Уровень 30
11 ноября 2024
Этот код демонстрирует использование ByteArrayInputStream для имитации ввода данных в стандартный поток System.in. Подробно разберем каждую часть. Разбор кода 1. Создание строки с данными: StringBuilder sb = new StringBuilder(); sb.append("Lena").append('\n'); sb.append("Olya").append('\n'); sb.append("Anya").append('\n'); String data = sb.toString(); Здесь создается объект StringBuilder, в который добавляются три строки: "Lena", "Olya", "Anya". Каждая строка завершается символом новой строки '\n'. В итоге в переменной data содержится строка: Lena Olya Anya 2. Создание ByteArrayInputStream: InputStream is = new ByteArrayInputStream(data.getBytes()); Строка data преобразуется в массив байтов с помощью метода data.getBytes(). Затем этот байтовый массив передается в конструктор ByteArrayInputStream, создавая поток is. ByteArrayInputStream — это поток ввода, который будет считывать данные из массива байтов (а не из реального источника, как файл или клавиатура). 3. Подмена System.in: System.setIn(is); Метод System.setIn(is) заменяет стандартный поток ввода System.in на is. Теперь любое чтение данных из System.in будет направлено к ByteArrayInputStream, содержащему наши строки.
Mabelod Уровень 30
11 ноября 2024
4. Вызов метода readAndPrintLine: readAndPrintLine(); Этот метод запускает чтение из System.in и выводит строки, не подозревая о том, что стандартный ввод был подменен на искусственный поток данных. 5. Чтение и вывод данных в readAndPrintLine: InputStreamReader isr = new InputStreamReader(System.in); BufferedReader reader = new BufferedReader(isr); Здесь создается InputStreamReader на основе System.in, который превращает поток байтов в поток символов. Затем BufferedReader оборачивает InputStreamReader, обеспечивая построчное чтение через метод readLine(). 6. Чтение строк в цикле: while (true) { String line = reader.readLine(); if (line == null) break; System.out.println(line); } Цикл читает строки из BufferedReader. Когда строки заканчиваются, readLine() возвращает null, что приводит к выходу из цикла. Внутри цикла каждая считанная строка выводится на экран с помощью System.out.println(line). 7. Закрытие потоков: reader.close(); isr.close(); Закрываются BufferedReader и InputStreamReader, что является хорошей практикой для освобождения ресурсов, хотя здесь это не обязательно, так как они работают с System.in, который не нужно закрывать в обычных условиях. Итог выполнения программы В результате программа выводит на экран строки: Lena Olya Anya Эти строки были помещены в ByteArrayInputStream, подменяющий стандартный ввод, и затем прочитаны методом readAndPrintLine, который, полагая, что читает из обычного System.in, выводит их построчно на экран.
Anonymous #3268884 Уровень 24
11 августа 2024
То есть суть кода в том, что когда жмем кнопку на клавиатуре, то событие нажатой кнопки вызывает не чтение буквы с нажатой кнопки, а чтение байта из какого-то буфера. Типа печатаем я-л-ю-б-л-ю-в-е-с-ь-м-и-р-! а вместо этого читается с-д-о-х-н-и-с-у-к-а-м-р-а-з-ь
G L Уровень 38
22 августа 2024
Суть кода чтоб показать принцип работы буфера, который мы заранее подготовили.
Dantes Уровень 1
21 сентября 2024
Finderpro Уровень 28
11 мая 2024
просто перелистну дальше, в надежде что поезде пойму
mkhlv Уровень 29
6 мая 2024
Что из этого обертка??
SomeBody098 Уровень 51
20 июня 2024
вроде ByteArrayInputStream