Skip to content

Ch 24: std::path路径操作

Path和PathBuf是Rust中处理路径的类型。它们是跨平台路径操作的基石。

  • Path - 路径的引用(&Path),不可变
  • PathBuf - 拥有的路径,可变

路径在Unix和Windows上的表示不同:

  • Unix:/home/user/file.txt
  • Windows:C:\Users\user\file.txt
use std::path::{Path, PathBuf};
fn main() {
// 从字面量创建Path
let path: &Path = Path::new("hello/world");
// 从&str创建PathBuf
let path_buf = PathBuf::from("hello/world");
// 从String创建PathBuf
let path_buf2 = PathBuf::from(String::from("hello/world"));
println!("Path: {:?}", path);
println!("PathBuf: {:?}", path_buf);
}
use std::path::Path;
fn main() {
let path = Path::new("home/user/document.txt");
// 迭代路径组件
for component in path.components() {
println!("component: {:?}", component);
}
// 输出:
// component: RootDir
// component: Normal("home")
// component: Normal("user")
// component: Normal("document.txt")
}
use std::path::Path;
fn main() {
let path = Path::new("document.txt");
// file_name 获取文件名
println!("file_name: {:?}", path.file_name());
// 输出: Some("document.txt")
// extension 获取扩展名
println!("extension: {:?}", path.extension());
// 输出: Some("txt")
// file_stem 获取文件名(不含扩展名)
println!("file_stem: {:?}", path.file_stem());
// 输出: Some("document")
}
use std::path::Path;
fn main() {
let path = Path::new("home/user/document.txt");
// parent 获取父路径
println!("parent: {:?}", path.parent());
// 输出: Some("home/user")
// ancestors 返回所有祖先路径
for ancestor in path.ancestors() {
println!("ancestor: {:?}", ancestor);
}
// 输出: "home/user", "home", ""
// is_root 检查是否是根路径
println!("is_root: {}", path.is_root());
}
use std::path::Path;
fn main() {
let full_path = Path::new("/home/user/document.txt");
// 去除前缀
let base = Path::new("/home/user");
if let Ok(relative) = full_path.strip_prefix(base) {
println!("相对路径: {:?}", relative);
// 输出: "document.txt"
}
// strip_prefix返回的是&Path
let relative = full_path.strip_prefix("/home").unwrap();
println!("去除/home后: {:?}", relative);
// 输出: "user/document.txt"
}
use std::path::Path;
fn main() {
let base = Path::new("/home/user");
// join 拼接路径
let full = base.join("documents");
let full2 = base.join("documents").join("file.txt");
println!("拼接1: {:?}", full);
// 输出: "/home/user/documents"
println!("拼接2: {:?}", full2);
// 输出: "/home/user/documents/file.txt"
// PathBuf的push
let mut path_buf = PathBuf::from("/home");
path_buf.push("user");
path_buf.push("file.txt");
println!("push后: {:?}", path_buf);
}
use std::path::Path;
fn main() {
let path = Path::new("/home/user/file.txt");
// starts_with 检查路径是否以指定前缀开始
println!("starts with /home: {}", path.starts_with("/home"));
println!("starts with /tmp: {}", path.starts_with("/tmp"));
// ends_with 检查路径是否以指定后缀结束
println!("ends with file.txt: {}", path.ends_with("file.txt"));
println!("ends with .txt: {}", path.ends_with(".txt"));
}
use std::path::Path;
fn main() {
let path = Path::new("hello/world");
// to_str 转换为&str(可能失败)
if let Some(s) = path.to_str() {
println!("to_str: {}", s);
}
// to_string_lossy 转换为String,替换无效字符
let lossy = path.to_string_lossy();
println!("to_string_lossy: {}", lossy);
// display 获取可以显示的引用
let path = Path::new("/home/user/中文.txt");
println!("display: {}", path.display());
}
use std::path::PathBuf;
fn main() {
let mut path = PathBuf::from("/home/user");
// push 添加路径组件
path.push("documents");
println!("push后: {:?}", path);
// pop 移除最后一个组件
path.pop();
println!("pop后: {:?}", path);
// set_file_name 设置文件名
path = PathBuf::from("/home/user/old.txt");
path.set_file_name("new.txt");
println!("set_file_name后: {:?}", path);
// set_extension 设置扩展名
path = PathBuf::from("/home/user/file.txt");
path.set_extension("md");
println!("set_extension后: {:?}", path);
// clear 清空
path.clear();
println!("clear后: {:?}", path);
}
use std::path::Path;
fn main() {
// Unix路径
let unix_path = Path::new("/home/user/file.txt");
println!("Unix路径组件数: {}", unix_path.components().count());
// Windows路径
#[cfg(windows)]
{
let win_path = Path::new("C:\\Users\\user\\file.txt");
println!("Windows路径组件数: {}", win_path.components().count());
}
}
use std::path::Path;
fn main() {
fn process_image(path: &Path) {
if let Some(ext) = path.extension() {
match ext.to_string_lossy().as_ref() {
"jpg" | "jpeg" => println!("JPEG图片"),
"png" => println!("PNG图片"),
"gif" => println!("GIF图片"),
_ => println!("未知格式"),
}
}
}
process_image(Path::new("photo.jpg"));
process_image(Path::new("image.png"));
}
use std::path::Path;
fn main() {
let messy = Path::new("./home/user/../user/./file.txt");
// components会返回规范化后的组件
let components: Vec<_> = messy.components()
.filter(|c| !matches!(c, std::path::Component::CurDir))
.collect();
println!("规范化组件: {:?}", components);
}
use std::fs;
use std::path::Path;
fn main() -> std::io::Result<()> {
let path = Path::new("test.txt");
// File::open 接受 AsRef<Path>
let file = fs::File::open(&path)?;
println!("文件打开: {:?}", file);
// fs::read 接受 AsRef<Path>
let content = fs::read(&path)?;
println!("文件大小: {} bytes", content.len());
// fs::write 接受 AsRef<Path>
fs::write(&path, "hello")?;
// 清理
fs::remove_file(&path)?;
Ok(())
}
方法说明
new(s)从字符串创建Path
file_name()获取文件名
extension()获取扩展名
file_stem()获取文件名(不含扩展名)
parent()获取父路径
ancestors()返回所有祖先路径
components()返回路径组件迭代器
strip_prefix(p)去除前缀
join(p)拼接路径
starts_with(p)检查前缀
ends_with(p)检查后缀
is_absolute()是否是绝对路径
is_relative()是否是相对路径
to_str()转换为&str
to_string_lossy()转换为String
display()获取Display引用

今天我们学习了std::path路径操作:

  1. Path/PathBuf - 路径的引用类型和拥有类型
  2. components - 迭代路径组件
  3. file_name/extension - 获取文件名和扩展名
  4. parent/ancestors - 获取父路径
  5. strip_prefix - 去除路径前缀
  6. join/push - 路径拼接
  7. starts_with/ends_with - 前缀后缀检查
  8. set_file_name/set_extension - 设置文件名/扩展名

Path和PathBuf是Rust中处理文件路径的标准方式,提供了跨平台的路径操作能力。