BufWriter
std::io::BufWriter<W> is a buffered output wrapper around any type W: Write (such as std::fs::File, std::net::TcpStream, or StdoutLock). It accumulates small writes inside an in-memory buffer (8 KiB = 8,192 bytes by default) and flushes them to the underlying writer W in large contiguous blocks, avoiding the overhead of issuing an OS write system call for every small field or line.
BufWriter<W> vs. LineWriter<W>
| Wrapper Type | Flush Trigger | Best Use Case |
|---|---|---|
BufWriter<W> |
Only when the 8 KiB buffer fills up, .flush() / .into_inner() is called, or BufWriter is dropped |
Bulk file generation (CSV, JSON, logs), binary network framing, batch StdoutLock output |
LineWriter<W> |
Whenever a newline byte \n is written (or when the buffer fills up) |
Interactive terminal output (used internally by std::io::Stdout) |
Writing 1,000 Short Lines to a `File`:
Unbuffered `File`:
1,000 `writeln!(file, ...)` calls ---> 1,000–2,000 OS `write()` syscalls!
Buffered `BufWriter<File>`:
1,000 `writeln!(buf_writer, ...)` ---> Appended in user-space RAM (`Vec<u8>`),
flushed in ~2–3 OS `write()` syscalls!
Key Constructors and Methods on BufWriter<W>
| Method | Signature | Behavior |
|---|---|---|
BufWriter::new(inner) |
pub fn new(inner: W) -> BufWriter<W> |
Creates a BufWriter with default 8,192-byte buffer capacity |
BufWriter::with_capacity(cap, inner) |
pub fn with_capacity(capacity: usize, inner: W) -> BufWriter<W> |
Creates a BufWriter with custom byte capacity |
.flush(&mut self) |
fn flush(&mut self) -> Result<()> |
Writes all buffered bytes to inner and flushes inner |
.into_inner(self) |
pub fn into_inner(self) -> Result<W, IntoInnerError<BufWriter<W>>> |
Flushes the buffer and returns the unwrapped W (or returns both the error and the BufWriter on failure!) |
.buffer(&self) |
pub fn buffer(&self) -> &[u8] |
Returns the slice of bytes currently waiting in the buffer |
.capacity(&self) |
pub fn capacity(&self) -> usize |
Returns the total byte capacity of the internal buffer |
Always Call .flush() or .into_inner() Before Dropping a BufWriter
Although BufWriter's Drop implementation attempts to flush any remaining buffered bytes when the BufWriter goes out of scope, Drop::drop cannot return an io::Result—so any disk-full or broken-connection error during automatic drop is silently ignored. Calling writer.flush()? (or let inner = writer.into_inner()?;) before the scope ends surfaces any final write error via Result:
use std::io::{self, BufWriter, Write};
fn main() -> io::Result<()> {
let mut backing_vec: Vec<u8> = Vec::new();
{
let mut writer = BufWriter::with_capacity(64, &mut backing_vec);
write!(writer, "header:")?;
write!(writer, "payload")?;
println!(
"before flush -> bytes in BufWriter RAM: {} B",
writer.buffer().len()
);
// Explicitly flush and check for errors before `writer` drops:
writer.flush()?;
println!(
"after flush -> bytes in BufWriter RAM: {} B",
writer.buffer().len()
);
}
println!(
"written to backing_vec: {:?}",
std::str::from_utf8(&backing_vec).unwrap()
);
Ok(())
}
before flush -> bytes in BufWriter RAM: 14 B
after flush -> bytes in BufWriter RAM: 0 B
written to backing_vec: "header:payload"