What exactly does "Stream" and "Buffer" mean in Java I/O?

Java has two kinds of classes for input and output (I/O): streams and readers/writers.

Streams (InputStream, OutputStream and everything that extends these) are for reading and writing binary data from files, the network, or whatever other device.

Readers and writers are for reading and writing text (characters). They are a layer on top of streams, that converts binary data (bytes) to characters and back, using a character encoding.

Reading data from disk byte-by-byte is very inefficient. One way to speed it up is to use a buffer: instead of reading one byte at a time, you read a few thousand bytes at once, and put them in a buffer, in memory. Then you can look at the bytes in the buffer one by one.

Oracle's Java tutorial about I/O explains it in detail.

Looking at the line of code you provided:

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

System.in is an InputStream. You create an InputStreamReader which reads bytes from System.in. Then you wrap that in a BufferedReader.

So, in the end, you have a BufferedReader that reads from an InputStreamReader that reads from System.in.


Buffer:

It is a region of a physical memory storage used to temporarily store data while it is being moved from one place to another. That physical memory storage would be RAM (Random-access memory) in most cases.

But from this question's context, Buffer is used while reading/writing data. It need not be used while moving data from one place to another.

Example for buffer: If your system has 4 GB of RAM, 4 KB of memory(RAM) could be allocated for Buffer by the system. KB - Kilobyte(s), GB - Gigabyte(s)

I/O Stream (or) Stream:

I/O Stream represents an input source or an output destination. A stream can represent many different kinds of sources and destinations, including disk files, devices, other programs, and memory arrays.

I/O means Input/Output.

So, Input Stream can be an input source like disk file, network connection, etc.

And, Output Stream can be an output destination like disk file, network connection, etc.

According to JAVA official documentation, Streams are of 3 types.

  1. Byte Streams (read or write Bytes)
  2. Character Streams (read or write Characters)
  3. Buffered Streams (read from, or write to, Buffer for efficiency)

Byte Streams:

They perform input and output of 8-bit bytes. All byte stream classes are descended from InputStream and OutputStream.

Byte Input Stream classes obtain input as raw bytes. Byte Output Stream classes give output as raw bytes.

InputStream - Direct Known Subclasses

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

OutputStream - Direct Known Subclasses

ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, OutputStream, PipedOutputStream

Character Streams: They are a layer on top of Byte Streams. They convert bytes(binary data) to characters and characters to bytes, using a character encoding.

All character stream classes are descended from Reader and Writer.

Reader - Direct Known Subclasses

BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader

Writer - Direct Known Subclasses

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

Byte Streams & Character Streams use unbuffered I/O.

This means each read or write request is handled directly by the underlying OS. This can make a program much less efficient, since each such request often triggers disk access, network activity, or some other operation that is relatively expensive. To reduce this kind of overhead, the Java platform implements buffered I/O streams.

Buffered Streams:

Buffered input streams read data from a memory area known as a buffer; the native input API is called only when the buffer is empty.

Similarly, buffered output streams write data to a buffer, and the native output API is called only when the buffer is full.

A program can convert an unbuffered stream into a buffered stream using the wrapping idiom, where the unbuffered stream object is passed to the constructor for a buffered stream class.

Example:

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

There are 4 buffered stream classes which are used to wrap unbuffered streams:

To create buffered Byte Streams use, BufferedInputStream and BufferedOutputStream classes.

To create buffered Character Streams use, BufferedReader and BufferedWriter classes.


Well its a question in everbodys mind who start working on java.io package. To answer your question terms InputStreamReader and BufferedReader represent the java objects only(there is nothing special about them) but they are created for io operations like reading and writing from/to different inputs/outputs like file, object etc

Now lets come to line

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

InputStreamReader is the class to read the input stream of bytes.But to read each byte is expensive operation so we are wrapping it around BufferedReader to have it buffered( which is decorator pattern)

So what will happen is even before you start read, bufferedReader will store some chunk of bytes in register and when you perform read operation. it will be read from that location which is much less expensive than reading from console/file But in case of InputStreamReader, when you perform read operation each time disk access operation takes place