Essential Standard Traits
Read and Write
The Read and Write traits in std::io provide byte-oriented synchronous input and output across files, TCP sockets, standard streams, and in-memory byte buffers.
Trait Definitions
pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize>;
// Provided methods:
// read_exact, read_to_end, read_to_string, bytes, chain, take, ...
}
pub trait Write {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize>;
fn flush(&mut self) -> std::io::Result<()>;
// Provided methods:
// write_all, write_fmt, by_ref, ...
}
Read::readpulls up tobuf.len()bytes intobufand returnsOk(n)indicating how many bytes were read (Ok(0)signals end-of-file whenbufis non-empty).Write::writewrites a prefix ofbufand returnsOk(n)bytes written;write_allloops until the entire slice is written.
Standard Types Implementing Read and Write
| Type | Implements Read? |
Implements Write? |
Notes |
|---|---|---|---|
std::fs::File |
Yes | Yes | Unbuffered OS file descriptor/handle |
std::net::TcpStream |
Yes | Yes | Unbuffered network socket |
&[u8] (byte slice) |
Yes | No | Reads from the slice and advances it in place |
Vec<u8> |
No | Yes | Appends written bytes to the end of the vector |
std::io::Cursor<T> |
Yes (if T: AsRef<[u8]>) |
Yes (for Vec<u8>, &mut [u8]) |
Adds a seekable position cursor to in-memory buffers |
BufReader<R> / BufWriter<W> |
BufReader<R> |
BufWriter<W> |
Wraps any Read or Write with an in-memory buffer to reduce syscalls |
Writing Testable I/O Code with Generic Read and Write
Accepting impl Read and impl Write instead of concrete File or TcpStream types lets you test I/O logic entirely in memory using &[u8] and Vec<u8>:
use std::io::{self, Read, Write};
fn copy_uppercase(mut reader: impl Read, mut writer: impl Write) -> io::Result<usize> {
let mut content = String::new();
reader.read_to_string(&mut content)?;
let upper = content.to_uppercase();
writer.write_all(upper.as_bytes())?;
writer.flush()?;
Ok(upper.len())
}
fn main() -> io::Result<()> {
let input: &[u8] = b"rust io traits";
let mut output: Vec<u8> = Vec::new();
let written = copy_uppercase(input, &mut output)?;
println!("Bytes written: {written}");
println!("Output text: {}", String::from_utf8_lossy(&output));
Ok(())
}
Bytes written: 14
Output text: RUST IO TRAITS