File IO
Create Files and Directories
Creating files and directories on disk takes time. Tokio provides non-blocking versions of these operations so your program does not have to stop and wait while the work is done.
File::create creates a new file. If the file already exists, it is overwritten.
create_dir creates a single directory. If it already exists, it fails.
create_dir_all creates a directory and any missing parent directories along the path.
This recipe requires the
macrosandfsfeature flags oftokioto be enabled inCargo.toml.
use std::io;
use tokio::fs::File;
#[tokio::main]
async fn main() -> io::Result<()> {
// create a file
File::create("data.txt").await?;
// create a single directory
tokio::fs::create_dir("my_dir").await?;
// create directory and missing parents
tokio::fs::create_dir_all("my_dir/sub_dir/inner").await?;
Ok(())
}
Read files
Reading a file from disk takes time. Tokio provides non-blocking versions of file reads so your program can keep doing other work while waiting for the data to come back.
readloads the file into raw bytes. Useful when you need to process the data directly.read_to_stringloads the file into plain text. Useful when you know the file contains readable characters.
This recipe requires the
macrosandfsfeature flags oftokioto be enabled inCargo.toml.
use std::io;
fn process_data(data: &[u8]) {
println!("Data Length: {}", data.len());
}
#[tokio::main]
async fn main() -> io::Result<()> {
// read to a Vec<u8>
let content = tokio::fs::read("data.txt").await?;
process_data(&content);
// read to a String
let str_content = tokio::fs::read_to_string("data.txt").await?;
process_data(str_content.as_bytes());
Ok(())
}
Write Files
Writing to disk takes time. tokio::fs::write is a non-blocking way to write bytes to a file.
It creates the file if it does not exist, or overwrites it if it does.
This recipe requires the
macrosandfsfeature flags oftokioto be enabled inCargo.toml.
use std::io;
#[tokio::main]
async fn main() -> io::Result<()> {
let content = b"Generic data from program!";
tokio::fs::write("data.txt", content).await?;
Ok(())
}
Remove Files and Directories
Deleting from disk takes time. Tokio provides non-blocking versions of these operations so your program does not have to stop and wait while the work is done.
remove_filedeletes a single file.remove_dirdeletes a single directory. Only works if the directory is empty.remove_dir_alldeletes a directory and everything inside it.
This recipe requires the
macrosandfsfeature flags oftokioto be enabled inCargo.toml.
use std::io;
#[tokio::main]
async fn main() -> io::Result<()> {
// remove a file
tokio::fs::remove_file("data.txt").await?;
// remove an empty directory
tokio::fs::remove_dir("my_dir").await?;
// remove a directory and all its contents
tokio::fs::remove_dir_all("my_dir").await?;
Ok(())
}
AsyncRead and AsyncWrite
AsyncRead and AsyncWrite are the building blocks for all non-blocking I/O in Tokio.
Any type that can be read from or written to non-blocking i.e file, a network stream, or
a buffer, implements one or both of these.
Their extensions AsyncReadExt and AsyncWriteExt add convenient methods on top:
write_allwrites bytes to a writer.read_to_endreads everything from a reader into a buffer.copystreams data from a reader directly into a writer.
This recipe requires the
macros,fsandio-utilfeature flags oftokioto be enabled inCargo.toml.
use std::io;
use tokio::fs::File;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
#[tokio::main]
async fn main() -> io::Result<()> {
// AsyncWrite: write bytes to a file
let mut file = File::create("data.txt").await?;
file.write_all(b"Generated Data!").await?;
// AsyncRead: read bytes from a file
let mut file = File::open("data.txt").await?;
let mut contents = Vec::new();
file.read_to_end(&mut contents).await?;
println!("Data Length: {}", contents.len());
// stream from reader to writer
let mut reader = File::open("data.txt").await?;
let mut writer = File::create("copy.txt").await?;
tokio::io::copy(&mut reader, &mut writer).await?;
Ok(())
}