Working with the File System in Rust: A Complete Guide
Rust is a modern systems programming language that offers powerful and safe tools for working with the file system. Thanks to its strict type system and ownership model, Rust helps avoid many errors related to file management, such as data races or resource leaks. In this article, we will thoroughly examine how to perform basic file system operations in Rust: creating, reading, writing, copying, and deleting files and directories. All code examples are written using the standard library std::fs.
Project Setup and Module Imports
To begin, create a new project using Cargo:
cargo new file_system_democd file_system_demoOpen the file src/main.rs and add the following imports:
use std::fs;use std::io::{self, Write, Read};use std::path::Path;The std::fs module provides functions for working with files and directories. std::io contains traits for input/output, and std::path::Path is for working with paths.
Creating and Writing Files
The simplest way to create a file and write data to it is to use the fs::write function. It takes a file path and content as bytes or a string.
fn main() -> io::Result<()> { // Create a file and write a string to it fs::write("hello.txt", "Hello, Rust!")?; println!("File created successfully."); Ok(())}If you need more control, use fs::File and the write or write_all methods:
fn main() -> io::Result<()> { let mut file = fs::File::create("data.txt")?; file.write_all(b"Data string")?; file.write_all("Another string".as_bytes())?; Ok(())}Note the ? — this is the error propagation operator. If the operation fails, the error will be returned from the function.
Reading Files
To read the entire contents of a file into a string, use fs::read_to_string:
fn main() -> io::Result<()> { let contents = fs::read_to_string("hello.txt")?; println!("File contents:{}", contents); Ok(())}If the file contains binary data, use fs::read, which returns Vec<u8>:
fn main() -> io::Result<()> { let data = fs::read("image.png")?; println!("Read {} bytes", data.len()); Ok(())}For line-by-line reading, it is convenient to use BufReader:
fn main() -> io::Result<()> { let file = fs::File::open("data.txt")?; let reader = io::BufReader::new(file); for line in reader.lines() { let line = line?; println!("{}", line); } Ok(())}Working with Directories
Creating a new directory is done using fs::create_dir or fs::create_dir_all (for nested paths):
fn main() -> io::Result<()> { // Create a single directory fs::create_dir("my_folder")?;
// Create nested directories (analogous to mkdir -p) fs::create_dir_all("a/b/c")?; println!("Directories created."); Ok(())}To check if a file or directory exists, use Path::exists:
fn main() { let path = Path::new("hello.txt"); if path.exists() { println!("File exists."); } else { println!("File not found."); }}To get a list of the contents of a directory, use fs::read_dir:
fn main() -> io::Result<()> { let e