Select Page

How to Read and Write to File in Rust

by | Programming, Rust, Tips

This tutorial will go through how to read and write to a file for Rust version 1.26+ and Rust version 1.0.


Read a File to String in Rust 1.26+

Rust provides straight-forward one-line functions for reading and writing. To read a file to string, we can use the std::fs::read_to_string() method. We have to specify the path to the file. Let’s look at an example of reading the host database under /etc/hosts:

fn main() {

    let info_str = std::fs::read_to_string("/etc/hosts").expect("File not able to be read");

    println!("{}", info_str);

}

We use expect() in the above code and the following examples to raise an exception method if the thread panics.

##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1	localhost
255.255.255.255	broadcasthost
::1             localhost

Read a File to String in Rust 1.0

In Rust 1.0, reading and writing to file is more verbose than the one-line functions. We still use the read_to_string() method, but we have to allocate a String or Vec before calling the method. This form is handy because we can reuse the allocated data or append it to an existing object. Let’s look at an example

use std::fs::File;
use std::io::Read;

fn main() {

    let mut info_str = String::new();
    
    let mut f = File::open("/etc/hosts").expect("Unable to open file");

    f.read_to_string(&mut info_str).expect("Unable to read string");

    println!("{}", info_str);

}
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1	localhost
255.255.255.255	broadcasthost
::1             localhost

Read a File to Vec<u8> in Rust 1.26+

To read a file to a Vec<u8> we can use the std::fs::read() method which accepts the path to the file as a parameter. We can convert the Vec<u8> object to a String using String::from_utf8_loss() method. Let’s look at an example.

fn main() {

    let info_vec = &std::fs::read("/etc/hosts").expect("The file could not be read");

    println!("{}", info_vec.len());

    let info_str  = String::from_utf8_lossy(info_vec);

    println!("{}", info_str);

}
365
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1	localhost
255.255.255.255	broadcasthost
::1             localhost

Read a File to Vec<u8> in Rust 1.0

For Rust 1.0, we have to allocate a Vec and open the file in read-only mode using File::open. Then we can call the read_to_end() method on the file object to read all the bytes until the end of the file and place them into the Vec. Let’s look at an example:

use std::fs::File;
use std::io::Read;

fn main() {

    let mut data = Vec::new();

    let mut f = File::open("/etc/hosts").expect("Unable to open file");

    f.read_to_end(&mut data).expect("Unable to read data");
 
    println!("{}", data.len());

    let info_string = String::from_utf8_lossy(&data);

    println!("{}", info_string);

}
365
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1	localhost
255.255.255.255	broadcasthost
::1             localhost

Write a File in Rust 1.26+

To write to a file in Rust 1.26+, we can the use std::fs::write() method. We have to specify the path to the file and the string we want to write to the file. Let’s look at an example:

fn main() {

    let data = "Rust\nis\nfun\nto\nlearn!";

    std:fs::write("write_test.txt", data).expect("Unable to write file");

}

Write a File in Rust 1.0

We can use the Write trait to write to a file in Rust 1.0. The write_all() method writes out data to file as bytes. We can convert a String/&str to bytes with as_bytes. Let’s look at an example:

use std::fs::File;
use std::io::Write;

fn main() {

    let data = "Rust\nis\nfun\nto\nlearn!";

    let path = "write_test.txt";

    let mut f = File::create(path).expect("Unable to create file");

    f.write_all(data.as_bytes()).expect("Unable to write data");
}

Buffered I/O

BufReader

Using a Read instance can be inefficient. For example, every call to read on TcpStream results in a system call.

A BufReader can improve the speed of programs that make small and repeated read calls to the same file or network socket.

However, read_to_end() copies data in large chunks, so the transfer may require fewer I/O requests than BufReader.

Let’s look at an example of using BufReader.

use std::fs::File;
use std::io::{BufReader, Read};

fn main() {

    let mut data = String::new();

    let f = File::open("/etc/hosts").expect("Unable to open file");

    let mut br = BufReader::new(f);

    br.read_to_string(&mut data).expect("Unable to read string");

    println!("{}", data);

}

We can also use BufReader to read the file line-by-line. Let’s look at an example to print the lines to the console.

use std::fs::File;
use std::io::{BufRead, BufReader};

fn main() {

    let f = File::open("/etc/hosts").expect("Unable to open file");

    let fb = BufReader::new(f);

    for line in fb.lines() {

        let line = line.expect("Unable to read line");

        println!("Line: {}", line);


    }
}
Line: ##
Line: # Host Database
Line: #
Line: # localhost is used to configure the loopback interface
Line: # when the system is booting.  Do not change this entry.
Line: ##
Line: 127.0.0.1	localhost
Line: 255.255.255.255	broadcasthost
Line: ::1             localhost

BufWriter

Let’s look at an example of using the BufWriter to write to a file using write_all(). The method will continuously call write() until there is no more data to write. We always have to write the data as bytes. We can convert a String/&str to bytes using as_bytes.

use std::fs::File;
use std::io::{BufWriter, Write};

fn main() {

    let data = "Some data!";

    let f = File::create("/tmp/foo").expect("Unable to create file");

    let mut fb = BufWriter::new(f);

    fb.write_all(data.as_bytes()).expect("Unable to write data");

}

Summary

Congratulations on reading to the end of this tutorial! We have gone through how to read and write to a file for Rust 1.0 and Rust 1.26+.

For further reading on Rust, go to the articles:

Have fun and happy researching!