跳到主要内容

Module io

搜索

Module io 

源代码
展开描述

用于异步 I/O 功能的 trait、辅助函数和类型定义。

此模块是 std::io 的异步版本。它主要定义了两个 trait:AsyncReadAsyncWrite,它们是标准库中 ReadWrite trait 的异步版本。

§AsyncRead and AsyncWrite

与标准库的 ReadWrite trait 一样,AsyncReadAsyncWrite 提供了用于读写输入和输出的最通用接口。然而,与标准库的 trait 不同,它们是异步的——这意味着从 tokio::io 类型读取或写入时,当 IO 未就绪时将让步给 Tokio 调度器,而不是阻塞。这允许在等待 IO 时运行其他任务。

另一个区别是,AsyncReadAsyncWrite 仅包含提供异步读写功能所需的核心方法。实用方法在 AsyncReadExtAsyncWriteExt 扩展 trait 中定义。这些 trait 会自动为分别实现了 AsyncReadAsyncWrite 的所有值实现。

最终用户很少会直接与 AsyncReadAsyncWrite 交互。相反,他们将使用扩展 trait 中定义的异步函数。库作者应实现 AsyncReadAsyncWrite 以提供表现为字节流的类型。

即使存在这些差异,Tokio 的 AsyncReadAsyncWrite trait 几乎可以与标准库的 ReadWrite 完全相同的方式使用。标准库中实现 ReadWrite 的大多数类型在 tokio 中都有实现 AsyncReadAsyncWrite 的异步等价物,例如 FileTcpStream

例如,标准库文档通过演示std::fs::File 读取一些字节来介绍 Read。我们可以使用 tokio::fs::File 做同样的事情:

use tokio::io::{self, AsyncReadExt};
use tokio::fs::File;

#[tokio::main]
async fn main() -> io::Result<()> {
    let mut f = File::open("foo.txt").await?;
    let mut buffer = [0; 10];

    // read up to 10 bytes
    let n = f.read(&mut buffer).await?;

    println!("The bytes: {:?}", &buffer[..n]);
    Ok(())
}

§Buffered Readers and Writers

基于字节的接口笨拙且效率低下,因为我们需要不断调用操作系统。为了解决这个问题,std::io 提供了对缓冲读写器的支持,因此 tokio::io 也提供了支持。

Tokio 提供了 std::io::BufRead trait 的异步版本 AsyncBufRead;以及异步的 BufReaderBufWriter 结构体,它们包装读写器。这些包装器使用缓冲区,减少了调用次数,并提供了更好的方法来访问你所需的内容。

例如,BufReaderAsyncBufRead trait 一起工作,为任何异步读取器添加额外的方法:

use tokio::io::{self, BufReader, AsyncBufReadExt};
use tokio::fs::File;

#[tokio::main]
async fn main() -> io::Result<()> {
    let f = File::open("foo.txt").await?;
    let mut reader = BufReader::new(f);
    let mut buffer = String::new();

    // read a line into buffer
    reader.read_line(&mut buffer).await?;

    println!("{}", buffer);
    Ok(())
}

BufWriter 没有添加任何新的写入方式;它只是缓冲对 write 的每次调用。但是,你必须 flush BufWriter 以确保任何缓冲的数据都已写入。

use tokio::io::{self, BufWriter, AsyncWriteExt};
use tokio::fs::File;

#[tokio::main]
async fn main() -> io::Result<()> {
    let f = File::create("foo.txt").await?;
    {
        let mut writer = BufWriter::new(f);

        // Write a byte to the buffer.
        writer.write(&[42u8]).await?;

        // Flush the buffer before it goes out of scope.
        writer.flush().await?;

    } // Unless flushed or shut down, the contents of the buffer is discarded on drop.

    Ok(())
}

§Implementing AsyncRead and AsyncWrite

因为它们是 trait,我们也可以为我们自己的类型实现 AsyncReadAsyncWrite。请注意,这些 trait 只能为与 futures 类型系统集成的非阻塞 I/O 类型实现。换句话说,这些类型绝不能阻塞线程,而是在 I/O 资源就绪时通知当前任务。

§Conversion to and from Stream/Sink

将字节的读写封装在数据的 StreamSink 中通常很方便。

Tokio 在 tokio-util crate 中提供了简单的包装器,用于在 AsyncReadStream 之间相互转换,请参阅 ReaderStreamStreamReader

还有一些实用 trait 抽象了编写自己的字节与结构化数据编码/解码适配器所需的异步缓冲,允许将实现了 AsyncRead/AsyncWrite 的内容转换为 Stream/Sink,请参阅 tokio-util::codec 模块中的 DecoderEncoder

§Standard input and output

Tokio 为标准输入输出错误提供了异步 API。这些 API 与 std 提供的 API 非常相似,但它们还实现了 AsyncReadAsyncWrite

请注意,标准输入/输出 API 必须在 Tokio 运行时的上下文中使用,因为它们需要 Tokio 特定的功能才能工作。在 Tokio 运行时之外调用这些函数会发生 panic。

§std re-exports

此外,ErrorErrorKindResultSeekFromstd::io 重新导出,以方便使用。

重新导出§

pub use std::io::Error;
pub use std::io::ErrorKind;
pub use std::io::Result;
pub use std::io::SeekFrom;

结构体§

Interest
Readiness event interest.
ReadBuf
A wrapper around a byte buffer that is incrementally filled and initialized.
Ready
Describes the readiness state of an I/O resources.

trait§

AsyncBufRead
Reads bytes asynchronously.
AsyncRead
Reads bytes from a source.
AsyncSeek
Seek bytes asynchronously.
AsyncWrite
Writes bytes asynchronously.