Rust 标准库 I/O
std::io 的 Read/Write/BufRead 抽象,错误类型,与文件/标准流的基本用法。
#concept
#growing
#dev
#rust
[!info] related notes
Rust 标准库 I/O
这个概念为什么出现
程序要与字节流交互:stdin、文件、socket、内存缓冲。
std::io 用小 trait 统一读写,错误用 std::io::Error。
[!abstract] 一句话理解
Read填充字节缓冲,Write写出字节,BufRead提供按行等缓冲读;它们组合出文件与网络 I/O 的共同语言。
最小可运行示例
场景:CLI 工具把一行提示写到 stdout 并回显大写
运维小工具从 stdin 读一行用户输入,去空白后转大写写回。
use std::io::{self, BufRead, Write};
// 业务意图:交互式读取一行并规范化输出。
// 教学点:stdin lock + BufRead;Write::write_all;io::Result。
fn main() -> io::Result<()> {
let stdout = io::stdout();
let mut out = stdout.lock();
out.write_all(b"input> ")?;
out.flush()?;
let stdin = io::stdin();
let mut input = stdin.lock();
let mut line = String::new();
if input.read_line(&mut line)? == 0 {
return Ok(()); // EOF,不把不存在的行当输入
}
let normalized = line.trim().to_uppercase();
writeln!(out, "normalized={normalized}")?;
out.flush()
}
建议运行 cargo run 后输入一行;无交互测试可用 printf ' cargo \n' | cargo run(POSIX shell)。
期望输出包含:
input> normalized=CARGO
结合场景再看三个关注点
?传播 io::Error- stdin.lock 实际读取标准输入;抽成接受 BufRead 的函数后,也可用 Cursor 注入内存测试数据
- 缓冲读写减少系统调用
核心概念与准确模型
| Trait | 作用 |
|---|---|
Read | read(&mut self, buf) -> Result<usize> |
Write | write / flush |
BufRead | read_line / lines |
File 实现 Read / Write / Seek,不直接实现 BufRead;按行读取通常包装 BufReader
设计动机
- 组合优于为每种介质写死 API
- 错误统一
- 同步 I/O 简单路径;async 另有生态
边界与误区
- 对非空目标缓冲,read 返回 Ok(0) 通常表示当前 EOF;传入空缓冲也可返回 0,增长中的文件以后仍可能有数据
- 标准库字节 I/O 不自动做平台文本模式换行转换;read_line 会保留换行并追加到已有 String,循环复用时需要 clear
- read_line 要求有效 UTF-8;任意字节按分隔符读取用 read_until,且需自行限制不可信输入行长度
- 阻塞 I/O 不适合直接当高并发服务器热路径
[!warning] 常见误区:忽略 write 的短写 使用
write_all或循环写完。
工程实践
- 测试用
Cursor/临时文件 - 大文件用缓冲
- 明确二进制 vs 文本
- 错误带路径上下文
本节总结
- Read/Write 统一字节流
- BufRead 提升文本处理
- 与文件系统笔记衔接
自测题
read返回Ok(0)通常意味着?- 为什么需要
flush?
参考答案
- 非空缓冲时通常为当前 EOF;空缓冲也可返回 0,不能一概当作永久结束。
- 将用户态缓冲推向下游并报告错误;不保证文件已持久写入磁盘,需要时另用文件 sync_all/sync_data。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| std::io | 标准库 | I/O 模块 |
| The Book — I/O | 官方书 | CLI I/O 项目 |