Use the std::fs::File type combined with std::io::Write to write data to a file, or use the convenience function std::fs::write for simple, one-shot operations. For more complex scenarios involving incremental writes or error handling, open a file with File::create or File::options and then call the write_all method.
Here is the simplest approach for writing a string directly to a file, which automatically handles opening, writing, and closing:
use std::fs;
use std::io;
fn main() -> io::Result<()> {
let text = "Hello, Rust world!";
fs::write("output.txt", text)?;
println!("File written successfully.");
Ok(())
}
If you need to append to an existing file, write multiple chunks, or handle binary data, use File::create (which truncates the file) or File::options (for appending). You must explicitly call write_all to ensure the buffer is flushed and the data is persisted:
use std::fs::File;
use std::io::{Write, BufWriter};
use std::io::Error;
fn main() -> Result<(), Error> {
// Create a new file (overwrites if exists)
let mut file = File::create("log.txt")?;
// Write a single string
file.write_all(b"Line 1\n")?;
// For better performance with many writes, wrap in a BufWriter
let mut buffer = BufWriter::new(file);
buffer.write_all(b"Line 2\n")?;
buffer.write_all(b"Line 3\n")?;
// Explicitly flush to ensure data is written to disk
buffer.flush()?;
Ok(())
}
Key points to remember:
- Error Handling: File I/O operations return
Resulttypes. Use the?operator to propagate errors up to themainfunction or handle them locally withmatch. - Bytes vs Strings:
write_allexpects a byte slice (&[u8]). If you have a&str, you must convert it using.as_bytes()or theb""prefix for literals. - Flushing: When using
BufWriter, data is buffered in memory. You must callflush()or ensure theBufWriteris dropped (which calls flush automatically) to guarantee the data hits the disk. - Permissions: Ensure the Rust process has write permissions for the target directory, or the operation will fail with a
PermissionDeniederror.