本页目录
字符串与 Path
&str是 UTF-8 保证的字节切片引用(String 是其堆分配版本),不能按s[0]索引(因为 UTF-8 一个字符 1-4 字节,O(1) 索引不成立)。OsStr是平台原生字符串(Unix 上就是字节,Windows 上是 WTF-8),Path是OsStr的路径封装——跨平台文件操作的正确做法是始终用 Path/PathBuf 而非字符串拼接。
String 与 &str: owned vs borrowed
let s: String = Stringfrom; // 堆分配, 可变, owned
let r: &str = "hello"; // 静态/借用, 不可变
String = Vec<u8> + UTF-8 validity guarantee——编译器保证 String 的内容始终是有效 UTF-8。可以通过 into_bytes() 取出底层 Vec<u8>(放弃 UTF-8 保证),也可以通过 from_utf8() 从 bytes 构造(返回 Result,无效 UTF-8 则 Err)。
为什么不能用 s[0]
在 C 中 s[0] 返回一个 byte——对 ASCII 没问题,对多语言完全不正确。在 Python 中 s[0] 返回第一个 Unicode code point——但 code point 不总是"可见字符"(é 可能是 e + ́,两个 code points)。
Rust 不把这种有隐藏成本的访问暴露为索引语法:
let s = "こんにちは"; // 5 个字符, UTF-8 中是 15 bytes
// let c = s[0]; // COMPILE ERROR: no indexing for String
let c = s.chars.nth.unwrap; // 'に' — O(2): 必须跳过前 2 个字符
UTF-8 是变长编码:ASCII 字符 1 byte,大多数西欧/中东字符 2 bytes,中日韩字符 3 bytes,emoji 4 bytes。s[n] 在 Rust 中不能是 O(1)——所以干脆不提供。程序员必须显式写 .chars().nth(n),承认"这需要扫描"。
OsStr/OsString: 非 UTF-8 的系统字符串
Unix 上的文件名只是 [u8]——可以是任意 bytes,不保证 UTF-8。Windows 上的文件名是 WTF-8(接近 UTF-16)。OsStr 是跨平台的抽象——不对内容做 UTF-8 保证,但能安全传递和拼接:
use OsStr;
use ;
let p = new;
let parent = p.parent.unwrap; // /usr
let file = p.file_name.unwrap; // bin
let full: PathBuf = p.join.join; // /usr/bin/subdir/file.txt
Path 只是 OsStr 的包装,加了路径专用方法(parent, extension, components, join)。PathBuf 是 owned 版本。关键在于:Path 不要求内容转为 String——你可以直接在 Path 上操作,无需先做 UTF-8 检查。
参考
- Rust Book: Chapter 8.2
- Rust Reference: OsStr, Path
Keywords: String, &str, UTF-8, char, OsStr, Path, PathBuf, indexing, Unicode