Handling Files and Directories in Rust

3601 VIEWS

Rust is one of the most beloved programming languages among developers (source). However, there isn’t much content out on the internet that covers various aspects of programming in Rust, like handling files.

Overview

It is a common practice to work with files when learning a new programming language. This is mostly because later on in our software development journey, we will always work with files. It may be for collecting logs or storing some particular type of information. There are not many articles that cover this particular aspect in Rust. That is why in this article I will be going over important file handling operations in Rust.

The Files Struct in Rust

Before we start digging through the various file operations, let us first have a brief understanding of what the Rust Files Struct is.

Firstly to understand what the File struct is, we need to know where it is imported from. It is imported from the fs standard module used for working with files.

The File struct is a type of struct used to carry out some file operations from the fs standard module.

We will use both the files standard module and the files struct for file manipulation.

Reading Files in Rust

To get started, we are first looking at how to read files in Rust. Firstly, let us create a new package where we will write our rust code.

We can do that with this command:

cargo new file_handling

After creating our package, we need to import the files module into our rust file within the src directory:

use std::fs;

Now that we have our files module imported, let us create a file we are going to work with. Within our working directory, create a new file called hello.txt.

The fs module has a built-in function available for us to read the contents of a file to a string called read_to_string. We can use it like so:

use std::fs; 
fn main() { 	
   let contents = fs::read_to_string("hello.txt).unwrap(); 	       
   println!("Contents {}", contents); 
}

Note: The read_to_string function returns the Result type Enum which is efficient for error handling, so we use the unwrap function to get its value.

We can also read the files using the files struct to achieve this.

use std::fs::File; 

fn main() { 	
   let mut file = fs::File::open("hello.txt"); 
   let mut content = String::new(); file.read_to_string(&mut content);          
   println!("Contents {}", content); 
}

In this case, we are opening the file using the File struct type and assigning its value to a mutable string, and finally printing out the string.

If an error occurs in reading from the file, we can handle it by using the expect method.

use std::fs::File; 

fn main () { 	
    let mut file = fs::File::open("hello.txt").expect("Error, could not open file"); 
    let mut content = String::new(); 
    file.read_to_string(&mut content).expect("Error, could not read file content"); 
    println!("Contents {}", content); 
}

Writing to Files in Rust

Similar to the built-in function used for reading files, there is also a built-in function used for writing to files.

use std::fs; 

fn main() { 	
    let new_content = String::from("This is new content"); 
    let file = fs::write("hello.txt", new_content); 
}

We can also write to files using the File struct.

use std::fs::File; 
fn main() { 	
    let file = File::create("hello.txt"); 
    file.write_all(b"This is new content"); 
}

In this case, the create function opens the file in write-mode only, which allows us to write to the file using byte-slices.

Note: Whenever we try to write to files using the method above, we completely overwrite the file we are writing to.

If we want to append to a file, we use a different approach.

use std::fs; 
use std::io::prelude::*; 

fn main() { 
    let mut file = fs::OpenOptions::new().append(true).open("hello.txt").unwrap();        l
    file.write(b"Hello World"); 
}

We import the io module which helps us write to the file which we have opened and stored using the file variable. Instead of importing just the Write functionality from the module, we import everything, just in case we have other operations we want to carry out.

Again, in the case whereby an error occurs in reading from the file, we can handle it by using the expect method.

use std::fs::File; 

fn main() { 	
    let file = File::create("hello.txt").expect("Could not create file");   
    file.write_all(b"This is new content").expect("Could not write to file"); 
}

Deleting Files in Rust

We can delete a file using the remove_file function.

use std::fs; 

fn main() { 	
    let file = fs::remove_file("hello.txt"); 
    println!("File was successfully deleted"); 
}

If by any chance the file deletion is going to be unsuccessful, you can handle the error by using the expect function, just like before.

use std::fs; 

fn main() { 	
    let file = fs::remove_file("hello.txt").expect("Error, file failed to delete"); 
    println!("File was successfully deleted"); 
}

Creating Directories in Rust

Similar to creating a file, we can also create a directory using the create_dir function.

fn main() { 	
    let new_dir = fs::create_dir("./some"); println!("New directory created"); 
}

Note: Make sure to add the period before the slash, if not you will get a Permission Denied error.

Renaming Directories in Rust 

Renaming directories is similar, there is a built-in function: rename.

fn main() { 	
   let rename_dir = fs::rename("./some", "./new"); println!("Directory renamed"); 
}

Deleting Directories in Rust1

We can delete directories using the remove_dir function.

fn main() { 	
    let delete_dir = fs::remove_dir("./new"); println!("Directory deleted"); 
}

To handle the errors when carrying out any of the operations mentioned above, use the expect function at the end of the operation’s function.

// Deleting directories

fn main() { 	
    let delete_dir = fs::remove_dir("./new").expect("Error, could not delete directory"); 
    println!("Directory deleted"); 
}

Conclusion

We went over some of the key operations with handling files and directories in Rust, such as reading from files, writing to files, writing to files, creating directories, renaming directories, and deleting directories. Now that you know the basics, happy coding!

Want to see more articles by Somtochukwu? Take a look here!


Somtochukwu is a backend engineer that loves explaining technical concepts as simply as he can through his articles.


Discussion

Leave a Comment

Your email address will not be published. Required fields are marked *

Menu
Skip to toolbar