Skip to content

Day 15: 文件与I/O

Rust标准库通过 std::fs 模块提供文件系统操作。读取文件有多种方式:

use std::fs;
use std::io;
// 方式1: read_to_string 一次性读取全部内容
fn read_entire_file(path: &str) -> Result<String, io::Error> {
fs::read_to_string(path)
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 读取整个文件
let content = fs::read_to_string("Cargo.toml")?;
println!("文件内容前100字符:");
println!("{}", &content[..content.len().min(100)]);
// 读取为字节数组
let bytes = fs::read("Cargo.toml")?;
println!("\n文件大小: {} 字节", bytes.len());
// 一行一行读取
let lines = fs::read_to_string("Cargo.toml")?;
for (i, line) in lines.lines().enumerate() {
if i < 5 {
println!("行 {}: {}", i + 1, line);
}
}
Ok(())
}
use std::fs::{self, File};
use std::io::{self, Write};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let content = "Hello, Rust!\n这是一次写入测试。";
// 方式1: write_all
let mut file = File::create("output.txt")?;
file.write_all(content.as_bytes())?;
// 方式2: write
let mut file = File::create("output2.txt")?;
file.write(content.as_bytes())?;
writeln!(file, "\n使用 writeln! 宏")?;
// 方式3: 使用 fs::write(一次性写入)
fs::write("output3.txt", "一次性写入的内容")?;
println!("文件写入成功!");
// 验证写入
let read_back = fs::read_to_string("output.txt")?;
println!("读取验证: {}", read_back);
Ok(())
}
use std::fs::{self, OpenOptions};
use std::io::Write;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let file_path = "append_test.txt";
// 首次写入
fs::write(file_path, "第一次写入\n")?;
// 追加模式打开文件
let mut file = OpenOptions::new()
.append(true)
.open(file_path)?;
writeln!(file, "第二次追加写入")?;
writeln!(file, "第三次追加写入")?;
// 读取验证
let content = fs::read_to_string(file_path)?;
println!("文件内容:\n{}", content);
Ok(())
}

对于大文件或频繁IO操作,使用缓冲可以显著提升性能:

use std::fs::{File};
use std::io::{self, BufRead, BufReader, BufWriter, Write};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建缓冲读取器
let file = File::open("Cargo.toml")?;
let reader = BufReader::new(file);
println!("使用 BufReader 读取 (前10行):");
for (i, line) in reader.lines().enumerate() {
if i >= 10 {
break;
}
println!("{}: {}", i + 1, line?);
}
// 创建缓冲写入器
let file = File::create("buffered_output.txt")?;
let mut writer = BufWriter::new(file);
for i in 1..=100 {
writeln!(writer, "第 {} 行内容", i)?;
}
// 重要: 需要 flush 确保数据写入
writer.flush()?;
println!("\n写入完成!");
Ok(())
}

Rust通过 std::env::args() 获取命令行参数:

use std::env;
fn main() {
// 获取所有参数
let args: Vec<String> = env::args().collect();
println!("命令行参数:");
for (i, arg) in args.iter().enumerate() {
println!(" [{}]: {}", i, arg);
}
// 访问特定参数
if args.len() > 1 {
println!("程序名: {}", args[0]);
println!("第一个参数: {}", args[1]);
}
// 使用 args_os 处理包含非UTF-8字符的参数
let args_os: Vec<std::ffi::OsString> = env::args_os().collect();
println!("\nOsString 形式的参数: {:?}", args_os.len());
}
use std::env;
use std::fs;
use std::io;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() != 3 {
eprintln!("用法: {} <源文件> <目标文件>", args[0]);
std::process::exit(1);
}
let source = &args[1];
let destination = &args[2];
match fs::copy(source, destination) {
Ok(bytes) => println!("复制成功! {} -> {} ({} 字节)", source, destination, bytes),
Err(e) => {
eprintln!("复制失败: {}", e);
std::process::exit(1);
}
}
}

编译并运行:

Terminal window
cargo build --release
./target/release/copy_tool Cargo.toml Cargo_copy.toml
use std::fs;
use std::path::Path;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建目录
fs::create_dir("test_dir")?;
// 创建嵌套目录
fs::create_dir_all("test_dir/subdir/nested")?;
// 读取目录内容
println!("目录内容:");
for entry in fs::read_dir(".")? {
let entry = entry?;
let path = entry.path();
let file_type = entry.file_type()?;
let name = entry.file_name();
if path.is_dir() {
println!(" [DIR] {}", name.to_string_lossy());
} else {
println!(" [FILE] {}", name.to_string_lossy());
}
}
// 检查路径存在性
println!("\ntest_dir 存在: {}", Path::new("test_dir").exists());
// 删除目录(必须是空目录)
fs::remove_dir("test_dir")?;
println!("\n目录操作完成!");
Ok(())
}

今天我们学习了Rust的文件与I/O操作:

  • 读取文件:fs::read_to_string、fs::read、BufReader
  • 写入文件:File::create、fs::write、追加模式 OpenOptions
  • 缓冲IO:BufReader 和 BufWriter 提升大文件操作性能
  • 命令行参数:std::env::args() 获取程序参数
  • 目录操作:create_dir、read_dir、remove_dir

文件I/O涉及错误处理,建议使用 ? 运算符传播错误。明天我们将学习闭包,这是Rust中的重要特性。