文件、路径、字节与编码
本章目标
这一章学习 Rust 如何读写文件、处理路径、理解字节和文本编码。你会知道为什么 Web 服务不能随便把 URL 拼成文件路径,以及 UTF-8 对中文内容为什么重要。
它是什么
文件是操作系统管理的持久化数据。路径是定位文件的位置。字节是最底层的数据单位。字符串则是在字节之上按编码解释出来的文本。
Rust 标准库常用类型:
std::fs:读写文件和目录。std::path::Path:借用路径。std::path::PathBuf:拥有路径。Vec<u8>:字节数组。String:UTF-8 文本。
为什么需要
当前项目有两类文件:
data/posts保存用户发布的文章。docs保存教材 Markdown。
它们都在磁盘上,但安全策略不同。文章通过数字 id 映射文件,文档通过静态章节清单映射文件。这样做是为了避免路径穿越,例如 /docs/../../Cargo.toml 不应该能读取项目配置。
怎么使用
读取文本文件:
let markdown = std::fs::read_to_string("docs/00-preface.md")?;
写入文本文件:
std::fs::write("data/example.txt", "hello")?;
构造路径:
use std::path::Path;
let path = Path::new("docs").join("00-preface.md");
逐行解释
fn chapter_path(slug: &str) -> std::path::PathBuf {
std::path::Path::new("docs").join(format!("{slug}.md"))
}
fn chapter_path定义一个把章节 slug 转成路径的函数。slug: &str借用章节标识。-> PathBuf返回拥有所有权的路径缓冲区。Path::new("docs")创建一个借用路径,表示 docs 目录。.join(...)拼接子路径,会使用当前操作系统的路径分隔规则。format!("{slug}.md")生成文件名。
在真实项目里,slug 必须来自可信清单或经过严格校验,不能直接使用用户输入。
常见坑
- 不要用字符串拼接处理跨平台路径,优先用
Path和PathBuf。 read_to_string要求文件是有效 UTF-8。- 用户输入不能直接参与文件路径,必须白名单或严格校验。
- 文本长度和字节长度不同,中文字符通常占多个字节。
练习
- 用
fs::write写入一个 UTF-8 中文文件。 - 用
read_to_string读回来并打印。 - 用
Path::new("docs").join("00-preface.md")构造路径。 - 尝试读取不存在文件,处理
Result。
造轮子任务
写一个安全文件读取器 read_registered_file(name: &str)。它只允许读取内置数组中登记过的文件名。传入未知文件名时返回 404 风格错误。这个任务和文档站章节白名单是同一个思想。
小结
文件系统 API 看似简单,但路径安全和编码细节非常重要。Rust 给了你 Path、Result、String、Vec<u8> 等明确类型,帮助你把文本、字节、路径和错误边界分清楚。