The two traits that run everything
`std::io::Read` and `std::io::Write` are the dual interfaces that every byte stream implements: files, sockets, stdin / stdout, in-memory buffers, encoders, decoders, and so on. Most useful functions in io take `impl Read` or `impl Write` so they work uniformly across every source and sink. Functions like `copy`, `read_to_string`, and `write_all` operate on the trait, not the concrete type.
Buffering matters
Raw `Read` and `Write` perform a syscall per call. Wrap them in `BufReader` / `BufWriter` whenever you do many small operations. For line-oriented input the `BufRead` trait (auto-implemented by `BufReader`) provides `lines()`, `read_line`, `read_until`. For output, `BufWriter` accumulates writes into a buffer and flushes either on demand or when dropped — call `flush()` explicitly before dropping if you care about the data being on disk.
For deeper background, see a complete cheat-sheet of std collection complexities for the broader context behind this section.
Errors are values, not exceptions
Every io call returns `io::Result<T>` (an alias for `Result<T, io::Error>`). The `io::Error` type has a `kind()` method returning a `std::io::ErrorKind` enum (NotFound, PermissionDenied, BrokenPipe, etc.) you can match on. The `?` operator makes propagating errors painless inside any function that itself returns `io::Result`.
Standard streams
`std::io::stdin()`, `stdout()`, and `stderr()` return locked-on-demand handles. For high-throughput output, lock the stream once with `let mut out = std::io::stdout().lock();` and write to it many times — every call to `stdout()` itself takes a lock internally, so caching the lock is faster.
For deeper background, see the official Rust API guidelines for module-level design for the broader context behind this section.
Cursors and in-memory streams
`std::io::Cursor<T>` lets you treat an in-memory `Vec<u8>` (or any `AsRef<[u8]>`) as something that implements both `Read` and `Write` and `Seek`. This is how you write tests for code that takes `impl Read` without touching the file system. For tiny in-memory writers, `Vec<u8>` itself implements `Write`.