Asynchronous I/O in Rust

Asynchronous I/O is essential for building non-blocking applications, such as servers, command-line tools, or GUIs. Rust provides robust support for asynchronous programming through the async/await syntax and libraries like tokio and async-std.

Getting Started with Async I/O

To perform asynchronous I/O, ensure you have an asynchronous runtime installed and the appropriate dependencies. Most users choose tokio, which is the most active and widely adopted async runtime in Rust:

Adding Dependencies

Add the following lines to your Cargo.toml file:

[dependencies]
tokio = { version = "1", features = ["full"] }

[build-dependencies]
tokio = { version = "1", features = ["build-time"] }
 
The tokio runtime is set up and async I/O is ready to be used.
 

Reading Asynchronously

Rust's standard library provides async_std or tokio-specific types to handle asynchronous input. For example, in tokio, use tokio::fs::File:

use tokio::fs::File;
use tokio::io::prelude::*;

#[tokio::main]
async fn main() {
 let mut file = File::open("example.txt")
 .await
 .expect("Failed to open file");

 let mut contents = String::new();
 file.read_to_string(&mut contents)
 .await
 .expect("Failed to read file");

 println!("File contents: {}", contents);
}
 
File contents: This is a sample text file for asynchronous I/O in Rust.
 

Writing Asynchronously

Writing data asynchronously also leverages the async APIs provided by the chosen runtime. In the example below, we'll write string data to a file using tokio:

use tokio::fs::File;
use tokio::io::prelude::*;

#[tokio::main]
async fn main() {
 let mut file = File::create("output.txt")
 .await
 .expect("Failed to create file");

 let data = "Hello, asynchronous Rust