Co dokładnie oznacza „Strumień” i „Bufor” w Java I / O?

85

Właśnie dowiedziałem się o używaniu wejścia / wyjścia BufferedReader.

Chciałem wiedzieć, jakie dokładnie są znaczenia tego terminu Streami Buffer?

Do czego służy nam ta linia kodu:

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
user122345656
źródło

Odpowiedzi:

202

Java ma dwa rodzaje klas wejścia i wyjścia (I / O): strumienie i czytniki / pisarze .

(Strumienie InputStream, OutputStreami wszystko, co rozszerza te) są do odczytywania i zapisywania danych binarnych plików z sieci, czy cokolwiek innego urządzenia.

Czytelnicy i pisarze są do czytania i pisania tekstu (znaków). Są warstwą na wierzchu strumieni, która konwertuje dane binarne (bajty) na znaki iz powrotem, przy użyciu kodowania znaków .

Odczytywanie danych z dysku bajt po bajcie jest bardzo nieefektywne. Jednym ze sposobów na przyspieszenie jest użycie bufora: zamiast czytać jeden bajt na raz, czytasz kilka tysięcy bajtów na raz i umieszczasz je w buforze w pamięci. Następnie możesz po kolei spojrzeć na bajty w buforze.

Samouczek Oracle dotyczący I / O w języku Java wyjaśnia to szczegółowo.

Patrząc na podany wiersz kodu:

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

System.injest InputStream. Tworzysz plik, InputStreamReaderktóry czyta bajty z System.in. Następnie zawijasz to w plik BufferedReader.

Więc w końcu masz, BufferedReaderktóry czyta z, InputStreamReaderktóry czyta System.in.

Jesper
źródło
1
Dziękuję za odpowiedź, ale nie mam wątpliwości. Jak powiedziałeś, czytamy kilka tysięcy bajtów na raz i umieszczamy je w buforze; czy to oznacza, że ​​bufor jest tylko miejscem w pamięci, w którym przechowujemy rzeczy?
user122345656
3
@Jesper. Powiedziałeś: „Jednym ze sposobów na przyspieszenie jest użycie bufora: zamiast czytać jeden bajt na raz, czytasz kilka tysięcy bajtów na raz i umieszczasz je w buforze, w pamięci. Następnie możesz spojrzeć na bajty w buforze jeden po drugim. " Tak, to prawda, ale myślę, że z buforem również, pojedynczy bajt jest odczytywany na raz Jedyna różnica myślę, że jest umieszczana w buforze i program, a następnie odczytuje go z bufora zamiast z dysku
M Sach
7
@ user122345656 Tak, bufor to miejsce w pamięci do tymczasowego przechowywania danych.
Jesper
14
@MSach Pomyśl o tym, co się dzieje, gdy chcesz odczytać dane z dysku twardego. Aby odczytać bajt w określonej lokalizacji, musisz poczekać, aż dysk się obróci, aż głowica znajdzie się nad miejscem na dysku, w którym znajduje się bajt do odczytania. Jeśli w tym momencie odczytasz tylko 1 bajt, a następny bajt później, będziesz musiał poczekać, aż dysk wykona pełny obrót, aby odczytać następny bajt. O wiele bardziej wydajne jest odczytywanie bloku kolejnych bajtów.
Jesper
2
@parsecer Strumienie służą do odczytu bajtów; czytelnicy służą do czytania tekstu (znaków). InputStreamReaderto opakowanie wokół elementu, InputStreamktóre umożliwia czytanie tekstu z pliku InputStream. Jeśli chcesz czytać tylko bajty (nie znaki), nie potrzebujesz InputStreamReader. Jest to przydatne, jeśli chcesz interpretować bajty jako znaki tekstowe.
Jesper
20

Bufor:

Jest to obszar pamięci fizycznej służący do tymczasowego przechowywania danych podczas przenoszenia ich z jednego miejsca do drugiego. W większości przypadków fizyczną pamięcią byłaby to pamięć RAM (pamięć o dostępie swobodnym).

Ale z kontekstu tego pytania, bufor jest używany podczas odczytu / zapisu danych. Nie trzeba go używać podczas przenoszenia danych z jednego miejsca do drugiego.

Przykład bufora: Jeśli twój system ma 4 GB pamięci RAM, 4 KB pamięci (RAM) może zostać przydzielone do bufora przez system. KB - kilobajt (y), GB - gigabajt (y)

Strumień I / O (lub) Strumień:

Strumień I / O reprezentuje źródło wejściowe lub miejsce docelowe wyjścia. Strumień może reprezentować wiele różnych rodzajów źródeł i miejsc docelowych, w tym pliki dyskowe, urządzenia, inne programy i tablice pamięci.

I / O oznacza wejście / wyjście.

Tak więc strumień wejściowy może być źródłem wejściowym, takim jak plik dyskowy, połączenie sieciowe itp.

Strumień wyjściowy może być miejscem docelowym, takim jak plik dyskowy, połączenie sieciowe itp.

Zgodnie z oficjalną dokumentacją JAVA , strumienie dzielą się na 3 typy.

  1. Strumienie bajtów (odczyt lub zapis bajtów)
  2. Strumienie znaków (odczyt lub zapis znaków)
  3. Buforowane strumienie (odczyt z bufora lub zapis do bufora w celu zwiększenia wydajności)

Strumienie bajtów:

Wykonują wejście i wyjście 8-bitowych bajtów. Wszystkie klasy strumienia bajtów pochodzą od InputStream i OutputStream .

Klasy Byte Input Stream uzyskują dane wejściowe jako nieprzetworzone bajty . Klasy Byte Output Stream dają dane wyjściowe jako nieprzetworzone bajty .

InputStream- Bezpośrednie znane podklasy

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

OutputStream- Bezpośrednie znane podklasy

ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, OutputStream, PipedOutputStream

Strumienie postaci: Są warstwą nad strumieniami bajtów. Konwertują bajty (dane binarne) na znaki i znaki na bajty, używając kodowania znaków.

Wszystkie klasy strumienia znaków pochodzą od Reader i Writer .

Reader - Bezpośrednie znane podklasy

BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader

Writer - Bezpośrednie znane podklasy

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

Strumienie bajtów i strumienie znaków używają niebuforowanych operacji we / wy .

Oznacza to, że każde żądanie odczytu lub zapisu jest obsługiwane bezpośrednio przez podstawowy system operacyjny. Może to znacznie obniżyć wydajność programu, ponieważ każde takie żądanie często wyzwala dostęp do dysku, aktywność sieciową lub inną operację, która jest stosunkowo kosztowna. Aby zmniejszyć tego rodzaju obciążenie, platforma Java implementuje buforowane strumienie we / wy.

Buforowane strumienie:

Buforowane strumienie wejściowe odczytują dane z obszaru pamięci zwanego buforem ; natywny wejściowy interfejs API jest wywoływany tylko wtedy, gdy bufor jest pusty.

Podobnie buforowane strumienie wyjściowe zapisują dane w buforze , a natywny wyjściowy interfejs API jest wywoływany tylko wtedy, gdy bufor jest pełny.

Program może konwertować niebuforowany strumień na buforowany strumień przy użyciu idiomu zawijania, w którym niebuforowany obiekt strumienia jest przekazywany do konstruktora dla klasy buforowanego strumienia.

Przykład:

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

Istnieją 4 klasy buforowanych strumieni, które są używane do zawijania niebuforowanych strumieni:

Aby utworzyć buforowane strumienie bajtów, użyj BufferedInputStreami BufferedOutputStreamklas.

Aby utworzyć buforowane strumienie znaków, użyj BufferedReaderi BufferedWriterklas.

AnV
źródło
1
Szukałem takiego dogłębnego wyjaśnienia dla java io. Dziękuję Ci bardzo.
Arif Reza,
14

Cóż, jest to pytanie dla każdego, kto zacznie pracować nad pakietem java.io. Aby odpowiedzieć na twoje pytanie, InputStreamReader i BufferedReader reprezentują tylko obiekty Java (nie ma w nich nic specjalnego), ale są tworzone dla operacji io, takich jak odczyt i zapis z / do różnych wejść / wyjść, takich jak plik, obiekt itp.

A teraz przejdźmy do kolejki

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

InputStreamReader to klasa do odczytu strumienia wejściowego bajtów, ale odczytanie każdego bajtu jest kosztowną operacją, więc owijamy go wokół BufferedReader, aby był buforowany (co jest wzorcem dekoratora)

Więc to, co się stanie, to jeszcze zanim zaczniesz czytać, bufferedReader zapisze kawałek bajtów w rejestrze i kiedy wykonasz operację odczytu. zostanie odczytany z tej lokalizacji, która jest znacznie tańsza niż odczyt z konsoli / pliku Ale w przypadku InputStreamReader, gdy wykonujesz operację odczytu za każdym razem, gdy ma miejsce operacja dostępu do dysku

M Sach
źródło
+1, ale wolałbym, żeby dodano odnośniki do dekoratora informacji i za każdym razem, gdy ma miejsce operacja dostępu do dysku
shareef
Ten ostatni akapit dobrze podsumowuje korzyści. Dziękuję za to.
Dave Voyles
3

Strumień to połączenie i rzeczywiste informacje przesyłane między punktami. Bufor to pojemnik do przechowywania, który przechowuje część lub całość przesyłanych strumieniowo danych i przekazuje je do urządzenia wyjściowego.

Oczywiście chodzi o to, że jeśli strumień zwalnia powyżej szybkości transmisji danych wymaganej do wyświetlenia danych, wyjście zatrzymywałoby się. Bufor zapobiega temu.

PGallagher
źródło
Dzięki za odpowiedzi. Ale pytanie, które przyszło mi do głowy, brzmi: co masz na myśli przez przesyłane strumieniowo dane?
user122345656
1
Przepraszam za późną odpowiedź. Jeśli wyobrażasz sobie prosty przykład pliku 10 MB na serwerze. Serwer ma pełny plik, ale nie może wysłać całego pliku w jednym pakiecie. Zamiast tego plik jest dzielony na skończoną liczbę bloków. Każdy blok jest następnie wysyłany do komputera zdalnego i ponownie składany. W przypadku przesyłania strumieniowego danych na żywo obowiązuje ta sama teoria. Ale serwer pobiera dane na żywo i wysyła je jako streampakiety. Następnie komputer zdalny przechowuje każdy pakiet w buforze. Komputer zdalny odczytuje dane ze swojego bufora i tworzy, powiedzmy, wideo z tego. Mam nadzieję, że to pomoże!
PGallagher
1

Bufor to część pamięci używana do przechowywania strumienia danych z urządzeń peryferyjnych. Następnie z tego bufora ten strumień danych jest zbierany i przechowywany w zmiennych. Strumień można zdefiniować jako ciągły przepływ danych.

Samo określenie „wejście / wyjście” oznacza nic innego jak przenoszenie danych do i z buforów. Po prostu miej to cały czas w pamięci. Procesy wykonują operacje we / wy, żądając od systemu operacyjnego, aby dane zostały usunięte z bufora (operacja zapisu) lub aby bufor został wypełniony danymi (operacja odczytu).
Schemat logiczny ruchu danych

Upraszczając, wyobraź sobie, że kiedy wpisujesz dane na klawiaturze, dane są przesyłane przez potok ( strumień ) do bufora, a następnie z bufora na dysk (operacja zapisu). Podobnie, gdy dane są przenoszone z dysku do bufora iz bufora na konsolę, jest to operacja odczytu.

Możesz przeczytać linki, aby lepiej zrozumieć. Mam nadzieję, że to pomoże!.
Co to jest bufor w Javie
wprowadź opis linku tutaj

Kushagra
źródło