跳到主要内容

Module io

搜索

Module io 

Source
展开描述

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

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

§AsyncRead and AsyncWrite

与标准库的 Read 和 Write trait 类似,AsyncRead 和 AsyncWrite 提供了用于读取和写入输入/输出 的最通用接口。 但与标准库的 trait 不同,它们 是异步的——这意味着对 tokio::io 类型进行读或写时,当 IO 还未就绪时会让出 给 Tokio 调度器,而不是阻塞。 这允许其他任务在等待 IO 时运行。

另一个区别是,AsyncRead 和 AsyncWrite 仅包含提供异步读写功能所需的核心方法。 而工具方法则定义在 AsyncReadExt 和 AsyncWriteExt 扩展 trait 中。 这些 trait 会自动为实现了 AsyncRead 和 AsyncWrite 的所有值实现。

最终用户很少会直接与 AsyncRead 和 AsyncWrite 交互, 而是使用扩展 trait 中定义的异步函数。 库的作者需要实现 AsyncRead 和 AsyncWrite, 以便提供表现为字节流行为的类型。

尽管存在这些差异,Tokio 的 AsyncRead 和 AsyncWrite trait 几乎可以以与标准库的 Read 和 Write 完全相同的方式使用。 标准库中大多数实现 Read 和 Write 的类型, 在 tokio 中都有实现了 AsyncRead 和 AsyncWrite 的异步等价物, 例如 File 和 TcpStream。

例如,标准库文档通过演示从 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(())
}

§带缓冲的 Readers 与 Writers

基于字节的接口使用起来很繁琐,效率也可能很低,因为我们几乎需要不停地调用操作系统。 为了解决这个问题,std::io 提供了对缓冲读取器和写入器的支持, 因此 tokio::io 也提供了这样的支持。

Tokio 提供了 std::io::BufRead trait 的异步版本 AsyncBufRead,以及异步的 BufReader 和 BufWriter 结构体, 它们包装了读取器和写入器。这些包装器使用缓冲区,减少了调用次数, 并提供了更方便的方法来精确访问你想要的内容。

例如,BufReader 与 AsyncBufRead 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,我们也可以为自己的类型实现 AsyncRead 和 AsyncWrite。 请注意,这些 trait 只能为与 futures 类型系统集成的非阻塞 I/O 类型实现。 换句话说,这些类型绝不能阻塞线程, 而应在 I/O 资源就绪时通知当前任务。

§Stream/Sink 之间的相互转换

通常,将字节的读写封装在数据的 Stream 或 Sink 中会很方便。

Tokio 在 tokio-util crate 中提供了简单的包装器, 用于在 AsyncRead 与 Stream 之间互相转换, 请参阅 ReaderStream 和 StreamReader。

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

§Standard input and output

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

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

§std re-exports

此外,Error、ErrorKind、Result 和 SeekFrom 从 std::io 重新导出,以方便使用。

重新导出§

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

结构体§

BufReader
BufReader 结构体 为任何 reader 添加缓冲。
BufStream
包装一个同时实现 AsyncWrite 和 AsyncRead 的类型, 并对其输入和输出进行缓冲。
BufWriter
包装一个 writer 并缓冲其输出。
Chain
chain 方法所用的流。
DuplexStream
用于在内存中读写字节的双向管道。
Empty
Empty 忽略通过 AsyncWrite 写入的任何数据, 并在通过 AsyncRead 读取时始终为空 (返回零字节)。
Interest
就绪事件兴趣位。
Join
将实现 AsyncRead 和 AsyncWrite 的两个值 合并为单个句柄。
Lines
从 AsyncBufRead 读取行。
ReadBuf
一个字节缓冲区的封装,会被增量填充和初始化。
ReadHalf
从 split 返回的值的可读一半。
Ready
描述 I/O 资源的就绪状态。
Repeat
一个异步 reader, 其反复、反复、反复地 产出一个字节。
SimplexStream
用于在内存中读写字节的单向管道。
Sink
一个将数据移入空白的异步 writer。
Split
split 方法所用的分割器。
Stderr
进程标准错误流的句柄。
Stdin
进程标准输入流的句柄。
Stdout
进程标准输出流的句柄。
Take
take 方法所用的流。
WriteHalf
从 split 返回的值的可写一半。

特性§

AsyncBufRead
异步地读取字节。
AsyncBufReadExt
为 AsyncBufRead 类型添加实用方法的扩展 trait。
AsyncRead
从一个数据源异步地读取字节。
AsyncReadExt
从一个数据源异步地读取字节。
AsyncSeek
异步地定位字节。
AsyncSeekExt
为 AsyncSeek 类型添加实用方法的扩展 trait。
AsyncWrite
异步地写入字节。
AsyncWriteExt
将字节写入 sink。

函数§

copy
异步地将 reader 的全部内容 复制到 writer。
copy_bidirectional
在 a 和 b 之间 双向复制数据。
copy_bidirectional_with_sizes
使用指定大小的缓冲区, 在 a 和 b 之间 双向复制数据。
copy_buf
异步地将 reader 的全部内容 复制到 writer。
duplex
创建一个新的 DuplexStream 对, 其行为类似一对连接的 socket。
empty
创建一个 读取时始终处于 EOF、 且忽略所有写入数据的值。
join
将实现 AsyncRead 和 AsyncWrite 的两个值 合并为单个句柄。
repeat
创建一个 无限重复单个字节的异步 reader 实例。
simplex
创建一个 行为类似内存管道的单向缓冲区。
sink
创建一个 将成功消费所有数据的 异步 writer 实例。
split
将一个 同时实现 AsyncRead + AsyncWrite 的值 分割为 单独的 AsyncRead 和 AsyncWrite 句柄。
stderr
构造一个 当前进程标准错误的 新句柄。
stdin
构造一个 当前进程标准输入的 新句柄。
stdout
构造一个 当前进程标准输出的 新句柄。