文件系统操作
🎯 文件系统编程概述
文件系统操作是系统编程的重要组成部分。Rust提供了从高级抽象到底层系统调用的完整文件操作能力。
📁 基础文件操作
标准库文件操作
rust
use std::fs::{File, OpenOptions, metadata, remove_file, rename};
use std::io::{Read, Write, Seek, SeekFrom};
use std::path::Path;
fn basic_file_operations() -> std::io::Result<()> {
// 创建文件
let mut file = File::create("example.txt")?;
file.write_all(b"Hello, File System!")?;
// 打开文件进行读取
let mut file = File::open("example.txt")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
println!("File contents: {}", contents);
// 文件元数据
let metadata = metadata("example.txt")?;
println!("File size: {} bytes", metadata.len());
println!("Is file: {}", metadata.is_file());
println!("Is directory: {}", metadata.is_dir());
// 重命名文件
rename("example.txt", "renamed_example.txt")?;
// 删除文件
remove_file("renamed_example.txt")?;
Ok(())
}
高级文件操作选项
rust
use std::fs::OpenOptions;
use std::io::{Write, Seek, SeekFrom};
fn advanced_file_operations() -> std::io::Result<()> {
// 使用OpenOptions进行精确控制
let mut file = OpenOptions::new()
.create(true) // 如果不存在则创建
.write(true) // 写入权限
.append(true) // 追加模式
.truncate(false) // 不截断文件
.open("advanced.txt")?;
// 追加内容
writeln!(file, "First line")?;
writeln!(file, "Second line")?;
// 重新打开文件进行随机访问
let mut file = OpenOptions::new()
.read(true)
.write(true)
.open("advanced.txt")?;
// 定位到文件开头
file.seek(SeekFrom::Start(0))?;
// 在开头插入内容(需要读取现有内容)
let mut contents = String::new();
file.read_to_string(&mut contents)?;
file.seek(SeekFrom::Start(0))?;
file.set_len(0)?; // 清空文件
write!(file, "Header\n{}", contents)?;
Ok(())
}
📂 目录操作
目录遍历和管理
rust
use std::fs::{self, DirEntry, create_dir_all, remove_dir_all};
use std::path::Path;
fn directory_operations() -> std::io::Result<()> {
// 创建目录结构
create_dir_all("test_dir/subdir1/subdir2")?;
// 在目录中创建文件
std::fs::write("test_dir/file1.txt", "Content 1")?;
std::fs::write("test_dir/subdir1/file2.txt", "Content 2")?;
// 列出目录内容
println!("Directory contents:");
for entry in fs::read_dir("test_dir")? {
let entry = entry?;
let path = entry.path();
let metadata = entry.metadata()?;
if metadata.is_dir() {
println!(" [DIR] {}", path.display());
} else {
println!(" [FILE] {} ({} bytes)", path.display(), metadata.len());
}
}
// 递归遍历目录
visit_dirs(Path::new("test_dir"), &|dir| {
println!("Visiting: {}", dir.display());
})?;
// 清理
remove_dir_all("test_dir")?;
Ok(())
}
fn visit_dirs(dir: &Path, cb: &dyn Fn(&Path)) -> std::io::Result<()> {
if dir.is_dir() {
cb(dir);
for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
visit_dirs(&path, cb)?;
} else {
cb(&path);
}
}
}
Ok(())
}
使用walkdir库进行高效遍历
rust
// 在Cargo.toml中添加: walkdir = "2"
use walkdir::WalkDir;
fn efficient_directory_traversal() {
for entry in WalkDir::new(".")
.follow_links(true)
.into_iter()
.filter_map(|e| e.ok())
{
let f_name = entry.file_name().to_string_lossy();
let sec = entry.metadata().unwrap().len();
if entry.file_type().is_file() {
println!("{} - {} bytes", f_name, sec);
} else if entry.file_type().is_dir() {
println!("[DIR] {}", f_name);
}
}
}
🔗 符号链接和硬链接
链接操作
rust
use std::os::unix::fs::{symlink, MetadataExt};
use std::fs::{hard_link, read_link};
#[cfg(unix)]
fn link_operations() -> std::io::Result<()> {
// 创建原始文件
std::fs::write("original.txt", "Original content")?;
// 创建硬链接
hard_link("original.txt", "hardlink.txt")?;
// 创建符号链接
symlink("original.txt", "symlink.txt")?;
// 检查链接
let original_meta = std::fs::metadata("original.txt")?;
let hardlink_meta = std::fs::metadata("hardlink.txt")?;
let symlink_meta = std::fs::symlink_metadata("symlink.txt")?;
println!("Original inode: {}", original_meta.ino());
println!("Hardlink inode: {}", hardlink_meta.ino());
println!("Symlink is symlink: {}", symlink_meta.file_type().is_symlink());
// 读取符号链接目标
let target = read_link("symlink.txt")?;
println!("Symlink target: {}", target.display());
// 清理
std::fs::remove_file("original.txt")?;
std::fs::remove_file("hardlink.txt")?;
std::fs::remove_file("symlink.txt")?;
Ok(())
}
🔐 文件权限和属性
Unix文件权限
rust
use std::os::unix::fs::PermissionsExt;
use std::fs::{self, Permissions};
#[cfg(unix)]
fn file_permissions() -> std::io::Result<()> {
// 创建文件
std::fs::write("perm_test.txt", "Permission test")?;
// 获取当前权限
let metadata = fs::metadata("perm_test.txt")?;
let permissions = metadata.permissions();
let mode = permissions.mode();
println!("Current permissions: {:o}", mode & 0o777);
// 设置新权限 (rw-r--r--)
let new_permissions = Permissions::from_mode(0o644);
fs::set_permissions("perm_test.txt", new_permissions)?;
// 验证权限更改
let metadata = fs::metadata("perm_test.txt")?;
let mode = metadata.permissions().mode();
println!("New permissions: {:o}", mode & 0o777);
// 清理
fs::remove_file("perm_test.txt")?;
Ok(())
}
// 权限检查辅助函数
#[cfg(unix)]
fn check_permissions(path: &str) -> std::io::Result<()> {
let metadata = fs::metadata(path)?;
let permissions = metadata.permissions();
let mode = permissions.mode();
println!("File: {}", path);
println!(" Owner: {}{}{}",
if mode & 0o400 != 0 { "r" } else { "-" },
if mode & 0o200 != 0 { "w" } else { "-" },
if mode & 0o100 != 0 { "x" } else { "-" }
);
println!(" Group: {}{}{}",
if mode & 0o040 != 0 { "r" } else { "-" },
if mode & 0o020 != 0 { "w" } else { "-" },
if mode & 0o010 != 0 { "x" } else { "-" }
);
println!(" Other: {}{}{}",
if mode & 0o004 != 0 { "r" } else { "-" },
if mode & 0o002 != 0 { "w" } else { "-" },
if mode & 0o001 != 0 { "x" } else { "-" }
);
Ok(())
}
🔍 文件监控
使用notify库监控文件变化
rust
// 在Cargo.toml中添加: notify = "5.0"
use notify::{Watcher, RecursiveMode, Result, Event, EventKind};
use std::sync::mpsc::channel;
use std::time::Duration;
fn file_monitoring() -> Result<()> {
let (tx, rx) = channel();
// 创建文件监控器
let mut watcher = notify::recommended_watcher(move |res: Result<Event>| {
match res {
Ok(event) => {
if let Err(e) = tx.send(event) {
println!("Failed to send event: {}", e);
}
}
Err(e) => println!("Watch error: {:?}", e),
}
})?;
// 监控当前目录
watcher.watch(std::path::Path::new("."), RecursiveMode::Recursive)?;
println!("Monitoring file changes. Press Ctrl+C to stop.");
// 处理文件变化事件
loop {
match rx.recv_timeout(Duration::from_secs(1)) {
Ok(event) => {
match event.kind {
EventKind::Create(_) => {
println!("File created: {:?}", event.paths);
}
EventKind::Modify(_) => {
println!("File modified: {:?}", event.paths);
}
EventKind::Remove(_) => {
println!("File removed: {:?}", event.paths);
}
_ => {
println!("Other event: {:?}", event);
}
}
}
Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
// 超时,继续监控
continue;
}
Err(e) => {
println!("Receive error: {}", e);
break;
}
}
}
Ok(())
}
💾 内存映射文件
大文件处理
rust
use memmap2::{Mmap, MmapOptions};
use std::fs::File;
fn memory_mapped_file_processing() -> Result<(), Box<dyn std::error::Error>> {
// 创建一个大文件用于测试
let mut file = File::create("large_file.dat")?;
file.set_len(1024 * 1024)?; // 1MB文件
// 重新打开文件进行内存映射
let file = File::open("large_file.dat")?;
let mmap = unsafe { Mmap::map(&file)? };
// 直接访问映射的内存
println!("File size: {} bytes", mmap.len());
// 搜索特定字节模式
let pattern = b"test";
if let Some(pos) = find_pattern(&mmap, pattern) {
println!("Pattern found at position: {}", pos);
} else {
println!("Pattern not found");
}
// 清理
drop(mmap);
std::fs::remove_file("large_file.dat")?;
Ok(())
}
fn find_pattern(data: &[u8], pattern: &[u8]) -> Option<usize> {
data.windows(pattern.len())
.position(|window| window == pattern)
}
🚀 异步文件操作
使用tokio进行异步文件I/O
rust
use tokio::fs::{File, OpenOptions};
use tokio::io::{AsyncReadExt, AsyncWriteExt, AsyncSeekExt};
async fn async_file_operations() -> tokio::io::Result<()> {
// 异步创建和写入文件
let mut file = File::create("async_test.txt").await?;
file.write_all(b"Async file content").await?;
file.flush().await?;
// 异步读取文件
let mut file = File::open("async_test.txt").await?;
let mut contents = Vec::new();
file.read_to_end(&mut contents).await?;
println!("Async read: {}", String::from_utf8_lossy(&contents));
// 异步追加内容
let mut file = OpenOptions::new()
.append(true)
.open("async_test.txt")
.await?;
file.write_all(b"\nAppended line").await?;
// 清理
tokio::fs::remove_file("async_test.txt").await?;
Ok(())
}
// 并发文件处理
async fn concurrent_file_processing() -> tokio::io::Result<()> {
let files = vec!["file1.txt", "file2.txt", "file3.txt"];
// 并发创建多个文件
let create_tasks: Vec<_> = files.iter().enumerate().map(|(i, &filename)| {
tokio::spawn(async move {
let content = format!("Content for file {}", i + 1);
tokio::fs::write(filename, content).await
})
}).collect();
// 等待所有创建任务完成
for task in create_tasks {
task.await??;
}
// 并发读取所有文件
let read_tasks: Vec<_> = files.iter().map(|&filename| {
tokio::spawn(async move {
tokio::fs::read_to_string(filename).await
})
}).collect();
// 收集结果
for (i, task) in read_tasks.into_iter().enumerate() {
let content = task.await??;
println!("File {}: {}", i + 1, content);
}
// 清理
for &filename in &files {
tokio::fs::remove_file(filename).await?;
}
Ok(())
}
🛠️ 文件系统工具
文件完整性检查
rust
use std::fs::File;
use std::io::{Read, BufReader};
use sha2::{Sha256, Digest};
fn calculate_file_hash(path: &str) -> std::io::Result<String> {
let file = File::open(path)?;
let mut reader = BufReader::new(file);
let mut hasher = Sha256::new();
let mut buffer = [0; 8192];
loop {
let bytes_read = reader.read(&mut buffer)?;
if bytes_read == 0 {
break;
}
hasher.update(&buffer[..bytes_read]);
}
Ok(format!("{:x}", hasher.finalize()))
}
fn verify_file_integrity() -> std::io::Result<()> {
// 创建测试文件
std::fs::write("integrity_test.txt", "Test content for integrity check")?;
// 计算原始哈希
let original_hash = calculate_file_hash("integrity_test.txt")?;
println!("Original hash: {}", original_hash);
// 模拟文件修改
std::fs::write("integrity_test.txt", "Modified content")?;
// 重新计算哈希
let new_hash = calculate_file_hash("integrity_test.txt")?;
println!("New hash: {}", new_hash);
if original_hash == new_hash {
println!("File integrity verified");
} else {
println!("File has been modified!");
}
// 清理
std::fs::remove_file("integrity_test.txt")?;
Ok(())
}
📊 性能优化
缓冲I/O优化
rust
use std::fs::File;
use std::io::{BufReader, BufWriter, Read, Write};
use std::time::Instant;
fn io_performance_comparison() -> std::io::Result<()> {
let data = vec![0u8; 1024 * 1024]; // 1MB数据
// 无缓冲写入
let start = Instant::now();
{
let mut file = File::create("unbuffered.dat")?;
for chunk in data.chunks(1024) {
file.write_all(chunk)?;
}
}
let unbuffered_time = start.elapsed();
// 缓冲写入
let start = Instant::now();
{
let file = File::create("buffered.dat")?;
let mut writer = BufWriter::new(file);
for chunk in data.chunks(1024) {
writer.write_all(chunk)?;
}
} // BufWriter在drop时自动flush
let buffered_time = start.elapsed();
println!("Unbuffered write: {:?}", unbuffered_time);
println!("Buffered write: {:?}", buffered_time);
println!("Speedup: {:.2}x",
unbuffered_time.as_secs_f64() / buffered_time.as_secs_f64());
// 清理
std::fs::remove_file("unbuffered.dat")?;
std::fs::remove_file("buffered.dat")?;
Ok(())
}
掌握文件系统操作是系统编程的基础技能,让我们继续探索更深层的系统编程主题!📁