AsyncRead and AsyncWrite

These two traits provide the facilities to asynchronously read from and write to byte streams. The methods on these traits are typically not called directly, similar to how you don’t manually call the poll method from the Future trait. Instead, you will use them through the utility methods provided by AsyncReadExt and AsyncWriteExt.

Let’s briefly look at a few of these methods. All of these functions are async and must be used with .await.

async fn read()

AsyncReadExt::read provides an async method for reading data into a buffer, returning the number of bytes read.

Note: when read() returns Ok(0), this signifies that the stream is closed. Any further calls to read() will complete immediately with Ok(0). With TcpStream instances, this signifies that the read half of the socket is closed.

  1. use tokio::fs::File;
  2. use tokio::io::{self, AsyncReadExt};
  3. #[tokio::main]
  4. async fn main() -> io::Result<()> {
  5. let mut f = File::open("foo.txt").await?;
  6. let mut buffer = [0; 10];
  7. // read up to 10 bytes
  8. let n = f.read(&mut buffer[..]).await?;
  9. println!("The bytes: {:?}", &buffer[..n]);
  10. Ok(())
  11. }

async fn read_to_end()

AsyncReadExt::read_to_end reads all bytes from the stream until EOF.

  1. use tokio::io::{self, AsyncReadExt};
  2. use tokio::fs::File;
  3. #[tokio::main]
  4. async fn main() -> io::Result<()> {
  5. let mut f = File::open("foo.txt").await?;
  6. let mut buffer = Vec::new();
  7. // read the whole file
  8. f.read_to_end(&mut buffer).await?;
  9. Ok(())
  10. }

async fn write()

AsyncWriteExt::write writes a buffer into the writer, returning how many bytes were written.

  1. use tokio::io::{self, AsyncWriteExt};
  2. use tokio::fs::File;
  3. #[tokio::main]
  4. async fn main() -> io::Result<()> {
  5. let mut file = File::create("foo.txt").await?;
  6. // Writes some prefix of the byte string, but not necessarily all of it.
  7. let n = file.write(b"some bytes").await?;
  8. println!("Wrote the first {} bytes of 'some bytes'.", n);
  9. Ok(())
  10. }

async fn write_all()

AsyncWriteExt::write_all writes the entire buffer into the writer.

  1. use tokio::io::{self, AsyncWriteExt};
  2. use tokio::fs::File;
  3. #[tokio::main]
  4. async fn main() -> io::Result<()> {
  5. let mut buffer = File::create("foo.txt").await?;
  6. buffer.write_all(b"some bytes").await?;
  7. Ok(())
  8. }

Both traits include a number of other helpful methods. See the API docs for a comprehensive list.