Sajiron
File I/O (input/output) is an essential part of most real-world applications. Whether you're building a config loader, log parser, or command-line tool, Rust gives you a powerful and safe set of tools to work with files and directories. In this guide, we’ll walk through the most important filesystem operations using Rust's standard library.
Rust lets you easily create and write to files using File::create
. This will create a file if it doesn’t exist or truncate it if it already does.
use std::fs::File;
use std::io::Write;
fn main() -> std::io::Result<()> {
let mut file = File::create("hello.txt")?;
file.write_all(b"Hello, Rust!")?;
Ok(())
}
File::create
returns a Result
type, so we use ?
to propagate errors. The write_all
method writes a byte string to the file.
To read from a file, you can use File::open
along with the Read
trait to load content into a string.
use std::fs::File;
use std::io::Read;
fn main() -> std::io::Result<()> {
let mut file = File::open("hello.txt")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
println!("File content: {}", contents);
Ok(())
}
This is great for reading text files. If you want a quicker way to do this, Rust offers a shortcut:
let contents = std::fs::read_to_string("hello.txt")?;
By default, writing to a file replaces its content. To append data instead, use OpenOptions
.
use std::fs::OpenOptions;
use std::io::Write;
fn main() -> std::io::Result<()> {
let mut file = OpenOptions::new()
.append(true)
.open("hello.txt")?;
file.write_all(b"\nAppended text!")?;
Ok(())
}
This allows you to open a file in append mode, preserving existing content while adding new data at the end.
Rust makes it easy to create directories using fs::create_dir
. For nested folders, you can use create_dir_all
.
use std::fs;
fn main() -> std::io::Result<()> {
fs::create_dir("my_folder")?;
Ok(())
}
If the directory already exists, this will return an error unless you handle it or use conditional logic.
To create nested directories:
fs::create_dir_all("my_folder/nested/inner")?;
Rust provides clear APIs for removing both files and directories. Use remove_file
for individual files, and remove_dir_all
for recursively removing directories and their contents.
fs::remove_file("hello.txt")?;
fs::remove_dir("my_folder")?;
fs::remove_dir_all("my_folder")?;
⚠️ Always double-check the path to avoid accidental deletions.
You can inspect the contents of a directory using fs::read_dir
, which returns an iterator over entries in the directory.
use std::fs;
fn main() -> std::io::Result<()> {
for entry in fs::read_dir(".")? {
let entry = entry?;
println!("{:?}", entry.path());
}
Ok(())
}
This is useful for building features like file explorers, folder analyzers, or tools that scan logs/configs.
Path
and PathBuf
Rust provides the Path
and PathBuf
types to represent file paths in a cross-platform way.
use std::path::Path;
fn main() {
let path = Path::new("hello.txt");
if path.exists() {
println!("File exists!");
}
if path.is_file() {
println!("It's a file.");
}
if path.is_dir() {
println!("It's a directory.");
}
}
These checks help ensure your program doesn’t crash due to invalid paths and work the same on Linux, macOS, and Windows.
Rust encourages developers to handle errors explicitly. You can use match
, if let
, or simply ?
to deal with Result
.
use std::fs::File;
fn main() {
match File::open("non_existent.txt") {
Ok(file) => println!("Opened file successfully!"),
Err(e) => eprintln!("Failed to open file: {}", e),
}
}
Proper error handling improves robustness and makes your tools more user-friendly.
Rust’s standard library gives you powerful tools to interact with the filesystem in a safe and reliable way. You’ve learned how to:
Create and write to files
Read and append file content
Work with folders
List directory contents
Use paths cross-platform
Handle errors effectively
Learn how to use Rust's core collections—Vec, HashMap, and String—with real-world examples, common methods, and usage patterns.
Build fast and safe frontend apps using Rust and Yew. Learn setup, components, hooks, and WebAssembly—all in a React-like Rust framework.
Learn how to structure Rust projects with packages, crates, and modules for better maintainability, reusability, and scalability.
Learn Rust async/await with futures, concurrency, and Tokio runtime. Master non-blocking programming, async streams, and efficient task execution. 🚀