Reading and Writing Files in Rust

Alex Garella

13th November 2023

In this blog post, we'll explore how to read from and write to files using Rust. This involves dealing with the std::fs and std::io modules. We will also explore how to handle potential errors effectively. Let's dive in!

Reading Files in Rust

Reading files in Rust is straightforward, thanks to its robust standard library. The std::fs and std::io modules are commonly used for this purpose.

Basic File Reading

Here's a simple example of how to read a file:

use std::fs::read_to_string; fn main() { match read_to_string("example.txt") { Ok(contents) => println!("File contents: \n{}", contents), Err(e) => println!("Error reading file: {}", e), } }

In this example, we use the read_to_string function to read the contents of the file into memory and print them out in case of success.

Reading Line by Line

Sometimes, when for example a file is too large to fit into memory, you might want to process a file line by line:

use std::fs::File; use std::io::prelude::*; use std::io::{BufReader, Lines, Result}; fn read_lines(file_path: &str) -> Result<Lines<BufReader<File>>> { let file = File::open(file_path)?; Ok(BufReader::new(file).lines()) } fn main() { match read_lines("example.txt") { Ok(lines) => { for line in lines { if let Ok(ip) = line { println!("{}", ip); } } } Err(e) => println!("Error reading file: {}", e), } }

Here, the read_lines function returns an iterator over the lines of the file, allowing for memory-efficient line-by-line processing.

The ? operator is used for error propagation, making the function return an Err immediately if any operation fails.

Writing Files in Rust

Writing to files is similarly easy in Rust. You typically use the std::fs and std::io modules as well.

Basic File Writing

Here's how you can write to a file:

use std::fs::File; use std::io::prelude::*; use std::io::Result; fn write_file(file_path: &str, contents: &str) -> Result<()> { let mut file = File::create(file_path)?; file.write_all(contents.as_bytes()) } fn main() { match write_file("output.txt", "Hello, Rust!") { Ok(_) => println!("File written successfully"), Err(e) => println!("Error writing file: {}", e), } }

This function write_file takes a file path and content to write. It creates or overwrites the file and writes the content to it.

Appending to a File

If you want to append to a file instead of overwriting it, you can use OpenOptions:

use std::fs::OpenOptions; use std::io::prelude::*; use std::io::Result; fn append_to_file(file_path: &str, contents: &str) -> Result<()> { let mut file = OpenOptions::new() .create(true) .write(true) .append(true) .open(file_path)?; file.write_all(contents.as_bytes()) } fn main() { match append_to_file("output.txt", "More text!\n") { Ok(_) => println!("Content appended successfully"), Err(e) => println!("Error appending to file: {}", e), } }

OpenOptions provides fine-grained control over file operations. The create method ensures that the file is created in case it does not exist and the append method ensures the contents are appended to the end of the file.

Error Handling

One of Rust's strengths is its robust error handling. In these examples, we've used the Result type for error handling, propagating errors with ? and matching them with match statements. This ensures that our file operations are safe and that any issues are properly addressed.


Rust makes reading and writing files efficient and safe with its powerful standard library and error handling capabilities. Whether you're dealing with large files, need to read line by line, or want to handle different file operations, Rust provides the tools you need to do so effectively.

Subscribe to receive the latest Rust jobs in your inbox

Receive a weekly overview of Rust jobs by subscribing to our mailing list

© 2024, All rights reserved.