Что именно означают Stream и Buffer в Java I/O?

Я только что узнал о вводе/выводе с помощью BufferedReader.

Я хотел знать, что именно означают термины Stream и Buffer?

И что нам служит эта строка кода:

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

person user122345656    schedule 13.04.2013    source источник


Ответы (5)


В Java есть два типа классов для ввода и вывода (I/O): потоки и читатели/писатели.

Потоки (InputStream, OutputStream и все, что их расширяет) предназначены для чтения и записи двоичных данных из файлов, сети или любого другого устройства.

Читатели и писатели предназначены для чтения и записи текста (символов). Это слой поверх потоков, который преобразует двоичные данные (байты) в символы и обратно, используя кодировку символов. .

Чтение данных с диска побайтно очень неэффективно. Один из способов ускорить это — использовать буфер: вместо того, чтобы читать по одному байту за раз, вы читаете сразу несколько тысяч байтов и помещаете их в буфер в памяти. Затем вы можете просмотреть байты в буфере один за другим.

Учебное пособие Oracle по Java о вводе-выводе объясняет это подробно.

Глядя на строку кода, которую вы предоставили:

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

System.in это InputStream. Вы создаете InputStreamReader, который считывает байты из System.in. Затем вы заворачиваете это в файл BufferedReader.

Итак, в конце концов, у вас есть BufferedReader, который читается из InputStreamReader, который читается из System.in.

person Jesper    schedule 13.04.2013
comment
Спасибо за ваш ответ, но у меня возникла путаница. Как вы сказали, мы читаем несколько тысяч байтов за раз и помещаем их в буфер; значит ли это, что буфер - это просто место в памяти, где мы храним вещи? - person user122345656; 13.04.2013
comment
@Джеспер. Вы сказали, что один из способов ускорить это — использовать буфер: вместо того, чтобы читать по одному байту за раз, вы читаете сразу несколько тысяч байтов и помещаете их в буфер в памяти. Затем вы можете просмотреть байты в буфере один за другим. Да, это правда, но я думаю, что с буфером также считывается один байт за раз. Единственное отличие, я думаю, что он помещается в буфер, а программа затем читает его из буфера, а не с диска. - person M Sach; 13.04.2013
comment
@user122345656 user122345656 Да, буфер — это место в памяти для временного хранения данных. - person Jesper; 14.04.2013
comment
@MSach Подумайте о том, что происходит, когда вы хотите прочитать данные с жесткого диска. Чтобы прочитать байт в определенном месте, вам нужно подождать, пока диск не повернется, пока головка не окажется над местом на диске, где находится считываемый байт. Если бы вы прочитали только 1 байт в этот момент, а следующий байт позже, вам пришлось бы ждать, пока диск не сделает полный оборот, чтобы прочитать следующий байт. Гораздо эффективнее читать блок последовательных байтов. - person Jesper; 14.04.2013
comment
ВАУ ! Очень хороший ответ. Очень легко понять и по делу. - person cram2208; 09.06.2016
comment
@Jesper В приведенном выше примере System.in считывает побайтно или кусками? Знает ли System.in о BufferedReader снаружи и читает кусками (в общем, что происходит первым — System.in или BufferedReader)? Мое естественное предположение — System.in, так как это отправная точка. Если это так, то он не будет знать о BufferedReader и, следовательно, не сможет выполнять массовое чтение, и, следовательно, какая польза от BufferedReader в этом примере? Не могли бы вы разделить выполнение еще более детально? - person user104309; 26.03.2017
comment
Думаю, я не особо задумывался об этом. Только после того, как вызывается какой-либо метод чтения BufferedReader, он инструктирует базовый считыватель (который, в свою очередь, инструктирует поток) читать массово и хранить его в буфере. Выполнение переходит в класс StreamDecoder, который должен ссылаться на System.in внизу, а StreamDecoder имеет положение (API) для массового чтения, и, следовательно, он будет выполнять массовое чтение из базового потока, которым является System.in, здесь. - person user104309; 26.03.2017
comment
@Jesper Будет ли по-прежнему выигрыш в производительности, даже если источник читается только один раз (без каких-либо операций, таких как пометка и сброс) с помощью буферизованной техники (по сравнению с небуферизованной)? - person lupchiazoem; 03.04.2018
comment
@San Да, потому что побайтовое чтение с чего-то вроде жесткого диска неэффективно; не имеет значения, читаете ли вы байты только один раз или несколько раз. - person Jesper; 04.04.2018
comment
Но какая разница между InputStreamReader и InputStream? Я могу читать из InputStream, используя метод inputstream.read() или метод inputstream.read(byte[]). Зачем нужен InputStreamReader? - person parsecer; 07.05.2019
comment
Потоки @parsecer предназначены для чтения байтов; читатели предназначены для чтения текста (символов). InputStreamReader — это оболочка вокруг InputStream, которая позволяет читать текст из InputStream. Если вы просто хотите читать байты (не символы), вам не нужен InputStreamReader. Это полезно, если вы хотите интерпретировать байты как текстовые символы. - person Jesper; 07.05.2019
comment
@Jesper Спасибо за ответ! Понятно. - person parsecer; 07.05.2019

Буфер:

Это область физического хранилища памяти, используемая для временного хранения данных во время их перемещения из одного места в другое. Этим хранилищем физической памяти в большинстве случаев будет ОЗУ (оперативная память).

Но из контекста этого вопроса Buffer используется при чтении/записи данных. Его не нужно использовать при перемещении данных из одного места в другое.

Пример для буфера: если в вашей системе 4 ГБ ОЗУ, 4 КБ памяти (ОЗУ) может быть выделено системой для буфера. КБ - килобайт(ы), ГБ - гигабайт(ы)

Поток ввода/вывода (или) Поток:< /сильный>

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

Ввод/вывод означает ввод/вывод.

Таким образом, Input Stream может быть источником ввода, например файлом на диске, сетевым подключением и т. д.

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

Согласно официальной документации JAVA, количество потоков составляет 3 типы.

  1. Byte Streams (чтение или запись байтов)
  2. потоки символов (чтение или запись символов)
  3. буферизованные потоки (чтение или запись в Буфер для эффективности)

Потоки байтов:

Они выполняют ввод и вывод 8-битных байтов. Все классы потока байтов происходят от InputStream и OutputStream.

Классы Byte Input Stream получают входные данные в виде необработанных байтов. Классы Byte Output Stream выдают выходные данные в виде необработанных байтов.

InputStream – Прямые известные подклассы

AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream.

OutputStream – Прямые известные подклассы

ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, OutputStream, PipedOutputStream

Character Streams. Это слой поверх байтовых потоков. Они преобразуют байты (двоичные данные) в символы и символы в байты, используя кодировку символов.

Все классы потока символов происходят от Reader и Писатель.

Reader - Прямые известные подклассы

BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader

Writer - Прямые известные подклассы

BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter

Потоки байтов и символов используют небуферизованный ввод-вывод.

Это означает, что каждый запрос на чтение или запись обрабатывается непосредственно базовой ОС. Это может сделать программу намного менее эффективной, так как каждый такой запрос часто инициирует доступ к диску, сетевую активность или какую-либо другую относительно дорогостоящую операцию. Чтобы уменьшить такие накладные расходы, платформа Java реализует буферизованные потоки ввода-вывода.

Буферизованные потоки:

Буферизованные входные потоки считывают данные из области памяти, известной как буфер; собственный API ввода вызывается только тогда, когда буфер пуст.

Точно так же буферизованные потоки вывода записывают данные в буфер, а собственный API вывода вызывается только при заполнении буфера.

Программа может преобразовывать небуферизованный поток в буферизованный поток, используя идиому переноса, где объект небуферизованного потока передается конструктору. для класса буферизованного потока.

Пример:

inputStream = new BufferedReader(new FileReader("xanadu.txt"));
outputStream = new BufferedWriter(new FileWriter("characteroutput.txt"));

Существует 4 класса буферизованных потоков, которые используются для переноса небуферизованных потоков:

Для создания буферизованных потоков байтов используйте классы BufferedInputStream и BufferedOutputStream.

Для создания буферизованных потоков символов используйте классы BufferedReader и BufferedWriter.

person AnV    schedule 18.08.2016
comment
Я искал такое подробное объяснение для java io. Большое Вам спасибо. - person Arif Reza; 07.11.2018

Ну, это вопрос для всех, кто начинает работать над пакетом java.io. Чтобы ответить на ваш вопрос, термины InputStreamReader и BufferedReader представляют только объекты Java (в них нет ничего особенного), но они созданы для операций ввода-вывода, таких как чтение и запись из/в различные входы/выходы, такие как файл, объект и т. д.

Теперь давайте подойдем к линии

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

InputStreamReader — это класс для чтения входного потока байтов. Но чтение каждого байта — дорогостоящая операция, поэтому мы оборачиваем его вокруг BufferedReader, чтобы буферизовать его (это шаблон декоратора).

Итак, что произойдет, еще до того, как вы начнете читать, bufferedReader сохранит некоторый кусок байтов в регистре и когда вы выполните операцию чтения. он будет прочитан из этого места, что намного дешевле, чем чтение из консоли/файла. Но в случае InputStreamReader, когда вы выполняете операцию чтения каждый раз, когда выполняется операция доступа к диску

person M Sach    schedule 13.04.2013
comment
+1, но я бы предпочел, чтобы была добавлена ​​​​ссылка на ссылки для декоратора информации, и каждый раз, когда операция доступа к диску выполняется, сообщения - person shareef; 13.11.2014
comment
Этот последний абзац хорошо суммирует преимущества. Спасибо за это. - person Dave Voyles; 01.10.2015

Поток — это соединение и фактическая информация, передаваемая между точками. Буфер — это контейнер для хранения, который хранит часть или все потоковые данные и передает их на устройство вывода.

Конечно, дело в том, что если скорость потока превышает скорость передачи данных, необходимую для отображения данных, вывод будет приостановлен. Буфер предотвращает это.

person PGallagher    schedule 13.04.2013
comment
Спасибо за ответ. Но у меня возник вопрос: что вы подразумеваете под потоковыми данными? Пожалуйста, уточните это. - person user122345656; 14.04.2013
comment
Извините за задержку с ответом. Если представить простой пример файла размером 10 Мб на сервере. Сервер имеет полный файл, но он не может отправить весь файл в одном пакете. Вместо этого файл разбивается на конечное число блоков. Затем каждый блок отправляется на удаленный компьютер и собирается заново. Для потоковой передачи данных в режиме реального времени применяется та же теория. Но сервер принимает оперативные данные и отправляет их в виде stream пакетов. Затем удаленный компьютер сохраняет каждый пакет в буфере. Удаленный компьютер считывает данные из своего буфера и создает, скажем, видео из этого. Надеюсь, это поможет! - person PGallagher; 16.04.2013

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

Сам термин «ввод/вывод» означает не что иное, как перемещение данных в буферы и из них. Просто постоянно держите это в уме. Процессы выполняют ввод-вывод, запрашивая у операционной системы данные для удаления из буфера (операция записи) или заполнения буфера данными (операция чтения).
Логическая схема перемещения данных

Проще говоря, представьте, что когда вы вводите данные на клавиатуре, данные перемещаются по каналу (поток) в буфер, а затем из буфера на диск (операция записи). Точно так же, когда данные перемещаются с диска в буфер и из буфера в вашу консоль, это операция чтения.

Вы можете прочитать ссылки для лучшего понимания. Надеюсь, это поможет!.
Что такое буфер в Java
введите здесь описание ссылки< /а>

person Kushagra    schedule 25.07.2019