Read & Write
Read lines of strings from a file
Writes a three-line message to a file, then reads it back a line at a
time with the Lines
iterator created by
BufRead::lines
. File
implements Read
which provides BufReader
trait. File::create
opens a File
for writing, File::open
for
reading.
use std::fs::File; use std::io::{Write, BufReader, BufRead, Error}; fn main() -> Result<(), Error> { let path = "lines.txt"; let mut output = File::create(path)?; write!(output, "Rust\nš\nFun\n")?; let input = File::open(path)?; let buffered = BufReader::new(input); for line in buffered.lines() { println!("{}", line?); } Ok(()) }
Buffered reading / writing is usually more efficient and faster than regular input / output operations.
Avoid writing and reading from a same file
Add this crate to your own project:
cargo add same_file
Use same_file::Handle
to a file that can be tested for equality with
other handles. In this example, the handles of file to be read from and
to be written to are tested for equality.
use same_file::Handle; use std::fs::File; use std::io::{BufRead, BufReader, Error, ErrorKind}; use std::path::Path; fn main() -> Result<(), Error> { let path_to_read = Path::new("content.txt"); let stdout_handle = Handle::stdout()?; let handle = Handle::from_path(path_to_read)?; if stdout_handle == handle { return Err(Error::new( ErrorKind::Other, "You are reading and writing to the same file", )); } else { let file = File::open(&path_to_read)?; let file = BufReader::new(file); for (num, line) in file.lines().enumerate() { println!("{} : {}", num, line?.to_uppercase()); } } Ok(()) }
cargo run --example same-file
displays the contents of the file content.txt.
cargo run --example same-file >> ./content.txt
errors because the two files are same.
Access a file randomly using a memory map
Add the memmap2
crate to your own project:
cargo add memmap2
Creates a memory map of a file using memmap and simulates some non-sequential
reads from the file. Using a memory map means you just index into a slice rather
than dealing with seek
to navigate a File.
The Mmap::map
function assumes the file
behind the memory map is not being modified at the same time by another process
or else a race condition occurs. This is why it needs to be enclosed
in an unsafe
block.
use memmap2::Mmap; use std::fs::File; use std::io::{Write, Error}; fn main() -> Result<(), Error> { write!(File::create("content.txt")?, "My hovercraft is full of eels!")?; let file = File::open("content.txt")?; let map = unsafe { Mmap::map(&file)? }; assert_eq!(&map[3..13], b"hovercraft"); let random_indexes = [0, 1, 2, 19, 22, 10, 11, 29]; let random_bytes: Vec<u8> = random_indexes.iter() .map(|&idx| map[idx]) .collect(); assert_eq!(&random_bytes[..], b"My loaf!"); Ok(()) }