Reading files in Rust, three ways

Rust gives you several levels of control when reading a file. Here are the three I actually use.

The one-liner

For small files, just slurp the whole thing:

1
2
3
4
5
6
7
use std::fs;

fn main() -> std::io::Result<()> {
let contents = fs::read_to_string("notes.txt")?;
println!("{} bytes", contents.len());
Ok(())
}

Buffered lines

For larger files, iterate line by line without loading everything:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use std::fs::File;
use std::io::{BufRead, BufReader};

fn main() -> std::io::Result<()> {
let file = File::open("notes.txt")?;
for line in BufReader::new(file).lines() {
let line = line?;
if line.starts_with('#') {
continue; // skip comments
}
println!("{line}");
}
Ok(())
}

Raw bytes

And when the file is not text at all:

1
let bytes = std::fs::read("image.png")?;

That covers 99% of everyday needs. The remaining 1% is memory-mapped IO, which is a story for another post.