Какво точно означават 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 и всичко, което ги разширява) са за четене и писане на двоични данни от файлове, мрежа или друго устройство.

Четците и записващите са за четене и писане на текст (символи). Те са слой над потоците, който преобразува двоични данни (байтове) в знаци и обратно, използвайки кодиране на знаци.

Четенето на данни от диска байт по байт е много неефективно. Един от начините да го ускорите е да използвате буфер: вместо да четете един байт наведнъж, вие четете няколко хиляди байта наведнъж и ги поставяте в буфер, в паметта. След това можете да разгледате байтовете в буфера един по един.

Урокът за Java на Oracle за I/O го обяснява подробно.

Разглеждайки предоставения от вас ред код:

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
@Jesper . Казахте, че един от начините да го ускорите е да използвате буфер: вместо да четете един байт наведнъж, вие четете няколко хиляди байта наведнъж и ги поставяте в буфер, в паметта. След това можете да разгледате байтовете в буфера един по един. Да, вярно е, но мисля, че и с буфера един байт се чете наведнъж. Единствената разлика, според мен се поставя в буфера и програмата след това го чете от буфера вместо от диска - person M Sach; 13.04.2013
comment
@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

Буфер:

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

Но от контекста на този въпрос Буфер се използва при четене/запис на данни. Не е необходимо да се използва при преместване на данни от едно място на друго.

Пример за буфер: Ако вашата система има 4 GB RAM, 4 KB памет (RAM) могат да бъдат разпределени за Буфер от системата. KB - Килобайт(ове), GB - Гигабайт(и)

I/O поток (или) поток:< /силен>

Входно-изходен поток представлява входен източник или изходна дестинация. Един поток може да представлява много различни видове източници и дестинации, включително дискови файлове, устройства, други програми и масиви от памет.

I/O означава вход/изход.

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

И изходният поток може да бъде изходна дестинация като дисков файл, мрежова връзка и т.н.

Според официалната документация на JAVA, потоците са от 3 видове

  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

Байтови потоци и символни потоци използват небуфериран I/O.

Това означава, че всяка заявка за четене или запис се обработва директно от основната операционна система. Това може да направи програмата много по-малко ефективна, тъй като всяка такава заявка често задейства достъп до диска, мрежова активност или някаква друга операция, която е сравнително скъпа. За да намали този вид режийни разходи, платформата Java прилага буферирани I/O потоци.

Буферирани потоци:

Буферираните входни потоци четат данни от област на паметта, известна като буфер; естественият входен 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 (няма нищо специално за тях), но те са създадени за io операции като четене и писане от/към различни входове/изходи като файл, обект и т.н.

Сега да дойдем на линия

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
Съжалявам за късния отговор. Ако си представите прост пример за 10Mb файл на сървъра. Сървърът има пълния файл, но не може да изпрати целия файл в един пакет. Вместо това файлът се разделя на краен брой блокове. След това всеки блок се изпраща до отдалечения компютър и се сглобява отново. За поточно предаване на данни на живо се прилага същата теория. Но сървърът взема живите данни и ги изпраща като stream пакети. След това отдалеченият компютър съхранява всеки пакет в буфер. Отдалеченият компютър чете данните от своя буфер и създава да речем видео от това. Надявам се това да помогне! - person PGallagher; 16.04.2013

Буферът е част от паметта, която се използва за съхраняване на поток от данни от периферни устройства. След това от този буфер този поток от данни се събира и съхранява в променливи. Потокът може да се дефинира като непрекъснат поток от данни.

Самият термин "вход/изход" не означава нищо повече от преместване на данни в и извън буферите. Просто дръжте това в ума си през цялото време. Процесите извършват I/O, като изискват от операционната система данните да бъдат източени от буфер (операция за запис) или буферът да бъде запълнен с данни (операция за четене).
Логическа диаграма за това как се движат данните

С прости думи, представете си, че когато въвеждате данни на клавиатура, данните се движат през канал (поток) към буфера и след това от буфера към диска (операция за запис). По подобен начин, когато данните се преместват от диск към буфер и от буфер към вашата конзола, това е операция за четене.

Можете да прочетете връзките за по-добро разбиране. Надявам се да помогне!.
Какво е буфер в Java
въведете описание на връзката тук

person Kushagra    schedule 25.07.2019