Rust - 文件输入/输出
Rust - 文件输入/输出 (现代版)
Section titled “Rust - 文件输入/输出 (现代版)”现代应用程序经常需要与文件系统交互。Rust 提供了一个健壮且安全的标准库模块 std::fs,用于处理文件输入/输出(I/O)。本教程涵盖了在 Rust 中使用文件的基本现代实践。
核心概念:Result 和错误处理
Section titled “核心概念:Result 和错误处理”几乎每个文件操作都可能因程序无法控制的原因(例如,文件未找到、权限被拒绝)而失败。Rust 使用 Result<T, E> 枚举来表示这些结果。与使用 .unwrap() 或 .expect() 导致崩溃不同,现代 Rust 代码使用 ? 运算符传播错误。这使得代码更简洁、更健壮。
要使用 ? 运算符,封闭函数必须返回 Result 类型。对于 main 函数,一个常见的签名是 fn main() -> std::io::Result<()>,这表示它可以返回任何标准 I/O 错误。
常见文件操作
Section titled “常见文件操作”std::fs 模块既提供高级便捷函数,也通过 File 结构体提供更底层的控制。
| No. | 函数 / 结构体 | 签名 (简化) | 描述 |
|---|---|---|---|
| 1 | std::fs::write | fn write<P, C>(path: P, contents: C) -> io::Result<()> | 这是一个便捷函数,用于打开文件、写入所有内容并关闭。如果文件不存在则创建,如果文件存在则覆盖。 |
| 2 | std::fs::read_to_string | fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> | 这是一个便捷函数,用于打开文件、将其全部内容读取到 String 中并关闭。 |
| 3 | std::fs::File::create | fn create<P: AsRef<Path>>(path: P) -> io::Result<File> | 以只写模式打开文件。创建新文件或截断现有文件。返回一个 File 句柄,用于更复杂的操作。 |
| 4 | std::fs::File::open | fn open<P: AsRef<Path>>(path: P) -> io::Result<File> | 以只读模式打开现有文件。返回一个 File 句柄。 |
| 5 | std::fs::OpenOptions | struct OpenOptions | 提供对文件打开方式(读、写、追加、创建等)的详细控制。这是最灵活的方法。 |
| 6 | std::fs::remove_file | fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> | 从文件系统中删除文件。 |
| 7 | std::io::Write::write_all | fn write_all(&mut self, buf: &[u8]) -> io::Result<()> | File 上的一个特性方法,尝试写入整个字节缓冲区。 |
| 8 | std::io::Read::read_to_string | fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> | File 上的一个特性方法,读取所有字节直到文件结束符(EOF)到字符串缓冲区中。 |
示例 1:简单写入和读取
Section titled “示例 1:简单写入和读取”对于简单任务,使用高级函数 fs::write 和 fs::read_to_string 是最直接的方式。请注意 main 函数的返回类型。
use std::fs;use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> { let file_path = "greeting.txt"; let content = "Hello, Modern Rust!\nThis is a new line.";
// 将内容写入文件,如果存在则覆盖 fs::write(file_path, content)?; println!("Successfully wrote to {}", file_path);
// 将整个文件读取到字符串中 let read_content = fs::read_to_string(file_path)?; println!("\n--- Reading from file ---"); print!("{}", read_content);
Ok(())}Successfully wrote to greeting.txt
--- Reading from file ---Hello, Modern Rust!This is a new line.示例 2:向文件追加内容
Section titled “示例 2:向文件追加内容”若要追加内容而不覆盖,我们使用 OpenOptions。我们通过链式调用方法来配置所需行为,然后调用 .open()。
use std::fs::OpenOptions;use std::io::Write;
fn main() -> std::io::Result<()> { let file_path = "log.txt";
let mut file = OpenOptions::new() .append(true) // 设置追加模式 .create(true) // 如果文件不存在则创建 .open(file_path)?;
file.write_all(b"LOG: Application started.\n")?; println!("Successfully appended to log file.");
Ok(())}示例 3:删除和复制文件
Section titled “示例 3:删除和复制文件”std::fs 模块还包含用于常见文件系统管理任务的简单函数。
use std::fs;
fn main() -> std::io::Result<()> { // 首先,确保我们有一个可以操作的文件 fs::write("source.txt", "This is the original file.")?;
// 复制文件 fs::copy("source.txt", "destination.txt")?; println!("Copied source.txt to destination.txt");
// 读取新文件进行验证 let content = fs::read_to_string("destination.txt")?; println!("Content of destination.txt: '{}'", content);
// 删除原始文件 fs::remove_file("source.txt")?; println!("Removed source.txt");
Ok(())}最佳实践:缓冲 I/O 以提高性能
Section titled “最佳实践:缓冲 I/O 以提高性能”当读取或写入大文件时,进行许多小的系统调用可能效率低下。Rust 的 std::io 模块提供了 BufReader 和 BufWriter,用于在内存中缓冲操作,从而减少系统调用并提高性能。
use std::fs::File;use std::io::{Write, BufWriter};
fn main() -> std::io::Result<()> { let file = File::create("large_log.txt")?; let mut writer = BufWriter::new(file);
for i in 0..1000 { writeln!(writer, "Entry number {}", i)?; }
// 当 `writer` 超出作用域时,缓冲区会自动刷新。 println!("Wrote 1000 entries with a BufWriter.");
Ok(())}