Java’s stream classes are good for streaming sequences of bytes, but
they’re not good for streaming sequences of characters because bytes and
characters are two different things. A byte represents an -bit data item
and a character represents a -bit data item. Also, Java’s char and String
types naturally handle characters instead of bytes. More importantly, byte
streams have no knowledge of character sets and their encodings.
Java provides writer and reader classes to stream characters. They support
character I/O (they work with char instead of byte) and take character
encodings into account. The abstract Writer and Reader classes describe
what it means to be a writer and a reader.
Writer and Reader are subclassed by OutputStreamWriter and
InputStreamReader, which bridge the gap between character and byte
streams. These classes are subclassed by the FileWriter and FileReader
convenience classes, which facilitate writing/reading characters to/from
files. Writer and Reader are also subclassed by BufferedWriter and
BufferedReader, which buffer characters for efficiency.