Что именно означают «поток» и «буфер» в Java I / O?

85

Я только что узнал об использовании ввода / вывода BufferedReader.

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

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

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
user122345656
источник

Ответы:

202

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

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

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

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

Java учебник Oracle, о I / O объясняет это в деталях.

Взглянув на предоставленную вами строку кода:

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

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

Итак, в конечном итоге у вас есть объект, BufferedReaderкоторый читает из файла, InputStreamReaderкоторый читает из System.in.

Джеспер
источник
1
Спасибо за ответ, но у меня замешательство. Как вы сказали, мы читаем сразу несколько тысяч байтов и помещаем их в буфер; значит ли это, что буфер - это просто место в памяти, где мы храним вещи?
user122345656
3
@ Джеспер. Вы сказали: «Один из способов ускорить это - использовать буфер: вместо того, чтобы читать по одному байту за раз, вы читаете сразу несколько тысяч байтов и помещаете их в буфер, в памяти. Затем вы можете посмотреть байты. в буфере по одному ". Да, это правда, но я думаю, что с буфером также читается один байт за раз. Единственная разница, я думаю, что он помещается в буфер, а программа затем читает его из буфера, а не с диска
M Sach
7
@ user122345656 Да, буфер - это место в памяти для временного хранения данных.
Jesper
14
@MSach Подумайте, что происходит, когда вы хотите прочитать данные с жесткого диска. Чтобы прочитать байт в определенном месте, вы должны подождать, пока диск не повернется, пока головка не окажется над местом на диске, где находится считываемый байт. Если вы читали только 1 байт в этот момент, а следующий байт позже, вам пришлось бы подождать, пока диск не совершит полный оборот, чтобы прочитать следующий байт. Гораздо эффективнее читать блок последовательных байтов.
Jesper
2
@parsecer Потоки предназначены для чтения байтов; ридеры предназначены для чтения текста (символов). InputStreamReader- это оболочка InputStream, позволяющая читать текст из InputStream. Если вы просто хотите читать байты (не символы), вам не нужно InputStreamReader. Это полезно, если вы хотите интерпретировать байты как текстовые символы.
Джеспер
20

Буфер:

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

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

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

Поток ввода / вывода (или) поток:

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

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

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

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

Согласно официальной документации JAVA , потоки бывают трех типов.

  1. Байтовые потоки (чтение или запись байтов)
  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

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

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

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 классов.

Для создания буферизованного Character Streams использовать, BufferedReaderи BufferedWriterклассы.

AnV
источник
1
Я искал такое подробное объяснение java io. Большое спасибо.
Ариф Реза
14

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

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

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

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

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

M Sach
источник
+1 но я бы предпочел, если бы добавил ссылку на ссылки для декоратора информации, и каждый раз, когда происходит операция доступа к диску, происходит
отправка
Последний абзац хорошо суммирует преимущества. Спасибо тебе за это.
Дэйв Войлс, 01
3

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

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

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

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

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

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

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

Кушагра
источник