Short answer
Unbuffered reads issue a system call per small read, and syscalls are expensive relative to memory copies, so reading a file byte-by-byte through a raw FileInputStream is orders of magnitude slower.
Explanation
A BufferedReader/BufferedInputStream reads a large block into an in-memory buffer once and serves your small reads from it, amortizing the syscall cost. The pitfall is forgetting to wrap (or wrapping in the wrong order), and forgetting that buffered output must be flushed/closed or the tail of your data never reaches disk.
Common mistakes
- Reading a file byte by byte without buffering.
- Wrapping an already-buffered stream again.