Rust 文件与 IO

读写文件、`BufReader`、路径操作、以及标准输入输出。

Intermediate
Key Points小文件用 `fs::read_to_string`,大文件用 `BufReader::lines()` 逐行。

一次性读写

Rust
use std::fs;
use std::io;

fn main() -> io::Result<()> {
    fs::write("demo.txt", "第一行\n第二行\n")?;

    let content = fs::read_to_string("demo.txt")?;
    print!("{}", content);
    println!("字节数 {}", content.len());

    // 二进制
    let bytes = fs::read("demo.txt")?;
    println!("字节数组长度 {}", bytes.len());

    Ok(())
}
Output
第一行
第二行
字节数 20
字节数组长度 20

fn main() -> io::Result<()> is a common pattern: when main returns Result, an error prints Error: ... and exits non-zero. Cleaner than unwrap everywhere.

逐行读大文件

Rust
use std::fs::File;
use std::io::{self, BufRead, BufReader};

fn main() -> io::Result<()> {
    let file = File::open("demo.txt")?;
    let reader = BufReader::new(file);

    for (i, line) in reader.lines().enumerate() {
        let line = line?;
        if line.contains("第二") {
            println!("第 {} 行命中:{}", i + 1, line);
        }
    }

    Ok(())
}
Output
第 2 行命中:第二行

BufReader reads 8 KB at a time and lines() slices from it. Calling lines() on a raw File works but makes one syscall per line — an order of magnitude slower.

写入

Rust
use std::fs::OpenOptions;
use std::io::{self, Write};

fn main() -> io::Result<()> {
    // 追加
    let mut f = OpenOptions::new()
        .create(true)
        .append(true)
        .open("log.txt")?;

    writeln!(f, "新日志 1")?;
    writeln!(f, "新日志 2")?;

    // 带缓冲写大量数据
    let mut buf = io::BufWriter::new(std::fs::File::create("big.txt")?);
    for i in 0..3 {
        writeln!(buf, "第 {} 行", i)?;
    }
    buf.flush()?;          // 必须

    Ok(())
}
Output
$ cat big.txt
第 0 行
第 1 行
第 2 行
MethodBehaviour
File::create创建或截断
OpenOptions::append追加
OpenOptions::create_new已存在则报错
BufWriter::flush把缓冲区写出去
BufWriter tries to flush on Drop but discards the error. Call flush()? explicitly or a full-disk error vanishes silently.

路径

Rust
use std::path::{Path, PathBuf};

fn main() {
    let p = Path::new("/tmp/demo/a.txt");

    println!("{:?}", p.file_name());
    println!("{:?}", p.extension());
    println!("{:?}", p.parent());
    println!("{}", p.display());

    // 拼接
    let mut buf = PathBuf::from("/tmp");
    buf.push("demo");
    buf.push("b.txt");
    println!("{}", buf.display());

    // 判断
    println!("{} {}", p.exists(), p.is_file());
}
Output
Some("a.txt")
Some("txt")
Some("/tmp/demo")
/tmp/demo/a.txt
/tmp/demo/b.txt
false false

Never build paths with string concatenation — Windows uses \, giving mixed separators like a/b\c. PathBuf::push handles the platform.

标准输入输出

Rust
use std::io::{self, Write};

fn main() {
    print!("请输入名字:");
    io::stdout().flush().unwrap();      // 保证提示先显示

    let mut input = String::new();
    io::stdin().read_line(&mut input).unwrap();
    let name = input.trim();

    println!("你好,{}", name);
}
Output
请输入名字:张三
你好,张三

print! without a newline may stay buffered so the user sees no prompt. Interactive programs must flush() after print!.

错误处理

Rust
use std::fs;
use std::io::ErrorKind;

fn main() {
    match fs::read_to_string("nope.txt") {
        Ok(s) => println!("{}", s),
        Err(e) if e.kind() == ErrorKind::NotFound => println!("文件不存在"),
        Err(e) if e.kind() == ErrorKind::PermissionDenied => println!("没有权限"),
        Err(e) => println!("其他错误:{}", e),
    }
}
Output
文件不存在

Friends & Partners