Memra

Byte streams vs character streams

◈ 4 cards

InputStream/OutputStream for raw bytes, Reader/Writer for text — and why the distinction matters.

Two families of streams

Java's classic I/O layer splits into two parallel hierarchies based on what you're moving:

Byte streams (InputStream / OutputStream) move raw binary data — eight bits at a time. Use them for images, audio, serialised objects, or any file where you cannot assume a text encoding.

Character streams (Reader / Writer) move decoded text — they handle charset conversion so your code sees char values rather than raw bytes. Use them whenever you are reading or writing text.

The bridge: InputStreamReader wraps an InputStream and decodes bytes to chars using a specified charset:

Reader reader = new InputStreamReader(System.in, StandardCharsets.UTF_8);

Buffering is almost always the right default — raw streams do one system call per read/write, which is slow. Wrap with a Buffered decorator:

BufferedReader br  = new BufferedReader(new FileReader("notes.txt"));
BufferedWriter bw  = new BufferedWriter(new FileWriter("out.txt"));

The three standard streams:

StreamTypePurpose
System.inInputStreamkeyboard / stdin
System.outPrintStreamnormal output / stdout
System.errPrintStreamerror output / stderr

PrintStream (which System.out and System.err use) is a convenience byte stream that adds print/println/printf — it is not a Writer despite printing text.

byte streamscharacter streamsinput rootInputStreamReaderoutput rootOutputStreamWritermovesraw bytesdecoded charsuse forimages, audio, .sertextbuffered wrapperBufferedInputStreamBufferedReaderInputStreamReader bridges the two.
Two parallel families with matching shapes — pick the column by what you are moving, not by what the class name sounds like. System.out sits on the byte side: it is a PrintStream, never a Writer, even though everything it prints is text.
NORMAL ~/memra/learn/java-from-zero/byte-vs-character-streams utf-8 LF