跳到主要内容

Module io

搜索

Module io 

Source
展开描述

异步 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(())
}

§带缓冲的 Readers 与 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 资源就绪时通知当前任务。

§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;

结构体§

BufReader
BufReader 结构体 为任何 reader 添加缓冲。
BufStream
包装一个同时实现 AsyncWriteAsyncRead 的类型, 并对其输入和输出进行缓冲。
BufWriter
包装一个 writer 并缓冲其输出。
Chain
chain 方法所用的流。
DuplexStream
用于在内存中读写字节的双向管道。
Empty
Empty 忽略通过 AsyncWrite 写入的任何数据, 并在通过 AsyncRead 读取时始终为空 (返回零字节)。
Interest
就绪事件兴趣位。
Join
将实现 AsyncReadAsyncWrite 的两个值 合并为单个句柄。
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
ab 之间 双向复制数据。
copy_bidirectional_with_sizes
使用指定大小的缓冲区, 在 ab 之间 双向复制数据。
copy_buf
异步地将 reader 的全部内容 复制到 writer。
duplex
创建一个新的 DuplexStream 对, 其行为类似一对连接的 socket。
empty
创建一个 读取时始终处于 EOF、 且忽略所有写入数据的值。
join
将实现 AsyncReadAsyncWrite 的两个值 合并为单个句柄。
repeat
创建一个 无限重复单个字节的异步 reader 实例。
simplex
创建一个 行为类似内存管道的单向缓冲区。
sink
创建一个 将成功消费所有数据的 异步 writer 实例。
split
将一个 同时实现 AsyncRead + AsyncWrite 的值 分割为 单独的 AsyncReadAsyncWrite 句柄。
stderr
构造一个 当前进程标准错误的 新句柄。
stdin
构造一个 当前进程标准输入的 新句柄。
stdout
构造一个 当前进程标准输出的 新句柄。