Rust 程序设计(第 2 版)
Jim Blandy, Jason Orendorff, Leonora F. S. Tindall
软件工程师
1469 人已学习
立即订阅
登录后,你可以任选4讲全文学习
推荐试读
换一换
课程目录
已完结/共 41 讲
时长 02:41
时长 06:30
时长 10:04
时长 01:05
时长 50:06
时长 31:35
时长 34:39
时长 29:11
时长 37:15
时长 23:44
时长 44:19
时长 29:54
时长 39:01
时长 01:38
时长 01:15
时长 00:37
Rust 程序设计(第 2 版)
15
15
1.0x
00:00/00:00
登录|注册

第 18 章 输入与输出

Doolittle:你有什么具体证据能证明你的存在?
炸弹 -20:嗯……好吧……我思故我在。
Doolittle:很好。非常好。但你又如何知道其他事物的存在呢?
炸弹 -20:我的感官感受到了。
——科幻喜剧《暗星》(Dark Star
Rust 标准库中的输入和输出的特性是围绕 3 个特型组织的,即 ReadBufReadWrite
实现了 Read 的值具有面向字节的输入方法。它们叫作读取器
实现了 BufRead 的值是缓冲读取器。它们支持 Read 的所有方法,外加读取文本行等方法。
实现了 Write 的值能支持面向字节和 UTF-8 文本的输出。它们叫作写入器
图 18-1 展示了这 3 个特型以及几个读取器类型和写入器类型的示例。
图 18-1:Rust 的 3 个主要 I/O 特型和一些实现了它们的类型
在本章中,我们会讲解如何使用这些特型及其方法,涵盖了图 18-1 中所示的这些读取器类型和写入器类型,并展示了与文件、终端和网络进行交互的其他方式。

18.1 读取器与写入器

你的程序可以从读取器中读取一些字节。例如:
使用 std::fs::File::open(filename) 打开的文件;
std::net::TcpStream,用于通过网络接收数据;
std::io::stdin(),用于从进程的标准输入流中进行读取;
std::io::Cursor<&[u8]> 值和 std::io::Cursor<Vec<u8>> 值,它们是从已存在于内存中的字节数组或向量中进行“读取”的读取器。
写入器则可以向其中写入一些字节。例如:
使用 std::fs::File::create(filename) 打开的文件;
std::net::TcpStream,用于通过网络发送数据;
std::io::stdout()std::io:stderr(),用于写入到终端;
Vec<u8> 也是一个写入器,它的 write 方法会把内容追加到向量;
std::io::Cursor<Vec<u8>>,它与 Vec<u8> 很像,但允许读取数据和写入数据,并能在向量中寻找不同的位置;
std::io::Cursor<&mut [u8]>,它与 std::io::Cursor<Vec<u8>> 很像,不过不能增长缓冲区,因为它只是一些现有字节数组的切片。
由于读取器和写入器都有标准特型(std::io::Readstd::io::Write),因此编写适用于各种输入通道或输出通道的泛型代码是很常见的。例如,下面是一个将所有字节从任意读取器复制到任意写入器的函数:
use std::io::;
const DEFAULT_BUF_SIZE: usize = 8 * 1024;
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W)
-> io::Result<u64>
where R: Read, W: Write
{
let mut buf = [0; DEFAULT_BUF_SIZE];
let mut written = 0;
loop {
let len = match reader.read(&mut buf) {
Ok(0) => return Ok(written),
Ok(len) => len,
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
};
writer.write_all(&buf[..len])?;
written += len as u64;
}
}
这是 Rust 标准库中 std::io::copy() 的实现。由于是泛型的,因此可以使用它将数据从 File 复制到 TcpStream,从标准输入复制到内存中的 Vec<u8>,等等。
如果对此处的错误处理代码不清楚,可以重温一下第 7 章。我们接下来还要不断使用 Result 类型,了解它的工作原理很重要。
std::ioReadBufReadWrite 这 3 个特型以及 Seek 非常常用,下面是一个只包含这些特型的 prelude 模块:
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Rust 标准库中的输入与输出特性主要围绕着三个主要特性组织,即 Read、BufRead 和 Write。Read 特性提供面向字节的输入方法,BufRead 特性是缓冲读取器,支持 Read 的所有方法外加读取文本行等方法,而实现了 Write 特性的值能支持面向字节和 UTF-8 文本的输出。本文介绍了这些特性及其方法的使用,包括读取器类型和写入器类型,并展示了与文件、终端和网络进行交互的其他方式。 文章还介绍了读取器和写入器的标准特性,以及编写适用于各种输入通道或输出通道的泛型代码是很常见的。此外,还介绍了 Read 特性的几个读取数据的方法,包括避免了对 ErrorKind::Interrupted 的手动处理。同时,展示了缓冲读取器的效率提高以及如何实现 Unix grep 实用程序的函数,并将其变成泛型函数以支持在磁盘上搜索文件。 对于写入器,文章介绍了输出发送、使用 write!() 和 writeln!() 宏以及文件的打开方法和寻址特性。此外,还介绍了其他读取器与写入器类型的使用。 总的来说,本文通过介绍 Rust 标准库中的输入与输出特性,为读者提供了对输入输出操作的全面了解,包括读取器和写入器的特性及其方法,以及如何与文件、终端和网络进行交互的方式。同时,还提及了一些开源 crate,如 byteorder、flate2 和 serde,以及它们提供的额外特性,如二进制输入输出方法、读取和写入 gzip 数据的适配器方法,以及序列化和反序列化的支持。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Rust 程序设计(第 2 版)》
立即购买
登录 后留言

精选留言

由作者筛选后的优质留言将会公开显示,欢迎踊跃留言。
收起评论
显示
设置
留言
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部