The File struct allows to create/read/overwrite files onto file systems. See Table 1 for some its methods. It implements the Read, Seek and io::Write traits that provide methods for moving cursor into file, read content and write content: see Table 2, Table 4 and Table 3.
Table 1:Some methods of File
Method | Description |
|---|---|
| Opens a file in read mode. |
| Opens a file in write mode. Creates a file if it does not exist or truncates it. |
| Opens a file in write node. Returns an error if the file already exists. |
| Equivalent to |
Table 2:Some methods of the Read trait
Method | Description |
|---|---|
| Chains another stream reader |
| Reads some bytes from this reader into the fixed size buffer |
| Reads exactly the number of bytes required to fill the fixed
size buffer |
| Reads all bytes from the stream up to EOF, placing into the
dynamic size buffer |
| Reads all bytes until EOF, and put them inside the |
Table 3:Some methods of the Seek trait
Method | Description |
|---|---|
| Rewinds to the start of the stream. |
| Moves the cursor to the position |
| Moves relative to the current position. |
| Returns the current position in the stream. |
Table 4:Some methods of the Write trait
Method | Description |
|---|---|
| Flushes the buffer, and makes sure all data is written onto the destination. |
| Writes the bytes buffer |
| Attempts to write the whole buffer |
36.4.1Write mode¶
To create a new file, we may use the create() method:
use std::fs::File;
let file = File::create("foo.txt")?;
fileA File object contains the following fields:
fd: The file descriptor. It is an identifier allocated by the operating system when a file is open.path: The file system path.read: Read mode activated.write: Write mode activated.
36.4.2OpenOptions¶
The OpenOptions
object allows us to customize the opening of a file for reading or
writing in any way possible. It is safer to use than the create()
method.
To create an OpenOptions object, we may use OpenOptions::new() or
File::options(). See Table 5 for a list of
methods of OpenOptions. In the following example, we create a new
OpenOptions object for which we enable writing, file creation,
and truncation of any existing file at this path:
let mut file = File::options().write(true).create(true).truncate(true)
.open("foo.txt")?;
fileTable 5:Methods of OptionOptions
Method | Description |
|---|---|
| Creates a new |
| Enables or disables append mode. |
| Enables or disables create mode. This mode creates a new file or opens it if it already exists. |
| Enables or disables create new mode. This mode creates a new file or returns an error if it already exists. |
| Opens a file at path |
| Enables or disables read mode. |
| Enables or disables truncate mode. |
| Enables or disables write mode. |
36.4.3The write!() and writeln!() macros¶
The write!() macro
is used to write into a write stream using either an
io::Write or a
fmt::Write
trait: it needs a write_fmt() method. The trait must be imported
with the use keyword in order to be accessible for the write!()
macro. It takes a as first argument the write stream (the file
object in our case), and then a string or a format string, and
eventually some arguments for the format string:
use std::io::Write;
writeln!(file, "Hello!")?;
write!(file, "a={:.2}", 12.345)?;36.4.4Closing a file¶
Closing a file is done by letting the File object go out of scope.
The closing provokes the flushing of the buffer and the release of
the file descriptor. Here we implement a function that writes a
file, the file will be closed when we leave the function:
use std::fs::File;
use std::io::Write;
use std::error::Error;
fn write_file(filename: &str) -> Result<(), Box<dyn Error>> {
let mut file = File::options().write(true).create(true).open(filename)?;
writeln!(file, "Hello!")?;
Ok(())
}
let filename = "hello.txt";
write_file(filename)?;36.4.5Appending to a file¶
To append to an existing file we just set the append flag:
fn append_file(filename: &str) -> Result<(), Box<dyn Error>> {
let mut file = File::options().append(true).open(filename)?;
writeln!(file, "Hello again!")?;
writeln!(file, "Nice day to you!")?;
Ok(())
}
append_file(filename)?;36.4.6Read mode¶
The Read trait provides functions to access the content of a
stream. To use it, we need to import with the use keyword. In the
following example, we use the read_to_string() method to load the
file’s content into a String instance:
use std::io::Read;
fn read_file(filename: &str) -> Result<(), Box<dyn Error>> {
let mut file = File::options().read(true).open(filename)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
println!("{}", contents);
Ok(())
}
read_file(filename)?;36.4.7BufRead trait¶
The BufRead
trait provides additional reading features like line by line
reading (see Table 6). It is implemented for instance
by the BufReader
structure, which can be instantiated from any object implementing the
Read trait: it will thus work on a File object.
use std::io::{BufRead, BufReader};
fn read_file_line_by_line(filename: &str) -> Result<(), Box<dyn Error>> {
let file = File::options().read(true).open(filename)?;
let buf = BufReader::new(file);
for (n, line) in buf.lines().enumerate() {
println!("Line n°{n}: {}", line?);
}
Ok(())
}
read_file_line_by_line(filename)?;Table 6:Methods of the BufRead trait
Method | Description |
|---|---|
| Returns an iterator over the lines of this reader. |
| Reads all bytes until a Line Feed (LF or |
| Reads all bytes until the byte |
| Skips all bytes up to byte |
| Returns an iterator over chunks (i.e.: bytes vectors) from this
reader, split on the byte |
36.4.8Checking the error type¶
The various functions of the std::fs module and the methods of all
its structures and traits return an
io::Error
object. Since file system errors are of many types, the io::Error
structure offers a way to check what happened and possibly take
action through the kind() method that returns an
io::ErrorKind
enum:
use std::error::Error;
use std::fs::File;
use std::io::ErrorKind;
use std::path::Path;
fn main() -> Result<(), Box<dyn Error>> {
let path = Path::new("input_data.txt");
let file = match File::open(path) {
Ok(f) => f,
Err(e) => match e.kind() {
ErrorKind::NotFound => File::options().create(true).write(true)
.read(true).open(path)?,
_ => return Err(Box::new(e)),
},
};
println!("{file:?}");
Ok(())
}
main()In this example:
The
open()method tries to open the file in read mode.Using the
options()method we creates the file, enabling both write and read modes.