本文属于我的 Rust 学习笔记 系列。
Rust 入门学习笔记以实际例子为主,讲解部分不是从零开始的,所以不建议纯萌新观看,读者最好拥有任意一种面向对象语言的基础,然后自己多多少少看过 Rust 的基本语法,刷过一点 rustlings。
来源:原子之音。当然也包含个人的一些补充。
视频
代码
Rust 进阶学习笔记以及实战的来源则五花八门,将会标注在下一行⬇️。
本节出处:原子之音 视频
基本操作
Rust 主要通过std::fs::File
来实现文件操作。
结构体File
可用于描述或操作一个文件。
File
的所有方法都会返回一个Result
枚举。
官方文档 中文文档。
文件的打开、创建、删除
File::open
使用只读模式打开一个文件。
- 返回文件句柄
- 文件不存在则抛出错误
File::create
使用只写模式打开一个文件。
- 文件存在则清空
- 文件不存在则新建
- 返回文件句柄
std::fs::OpenOptions
可设置为追加模式
std::fs::remove_file
从文件系统删除一个文件,注意删除文件的方法在 fs 下面,和 File 是没有关系的!
例子
use std::io::Write;
fn main() -> std::io::Result<()> {
let f = std::fs::File::open("README.md");
println!("{:?}", f); let mut f = std::fs::File::create("foo.txt")?;
println!("{:?}", f);
f.write("中文".as_bytes())?; f.write_all(b"hello!")?;
std::fs::remove_file("foo.txt")?;
Ok(())
}
读写操作
读取文件的方式
use std::io::{BufRead, BufReader, Read, Write};
fn main() -> std::io::Result<()> {
let mut file = std::fs::File::open("README.md")?;
let mut data = Vec::new();
file.read_to_end(&mut data)?;
println!("{:?}", data);
let mut file = std::fs::File::open("README.md")?;
let mut content = String::new();
file.read_to_string(&mut content)?;
println!("{:?}", content);
let mut file = std::fs::File::open("README.md")?;
let reader = BufReader::new(file);
for (index, line) in reader.lines().enumerate() {
let line = line?;
println!("{}. {}", index + 1, line);
}
Ok(())
}
写文件的方式
- 新建
- 追加:
std::fs::OpenOptions::new().append(true).open("foo.txt");
use std::env;
use std::io::Write;
fn main() -> std::io::Result<()> {
let temp_dir = env::temp_dir();
println!("{:?}", temp_dir);
let temp_file = temp_dir.join("temp.txt");
let mut file = std::fs::File::create(&temp_file)?; writeln!(&mut file, "字符串")?;
file.write(b"111111111111111111111111111111111111111111111111111111111111111111111111111111")?;
let mut file = std::fs::OpenOptions::new().append(true).open(temp_file)?;
file.write_all("\n1111111111111111111111111".as_bytes())?;
Ok(())
}
路径操作
Rust 路径操作都在std::fs
下,包括create_dir
、remove_dir
等。
下面例子出处。
use std::fs;
use std::fs::{File, OpenOptions};
use std::io;
use std::io::prelude::*;
#[cfg(target_family = "unix")]
use std::os::unix;
#[cfg(target_family = "windows")]
use std::os::windows;
use std::path::Path;
fn cat(path: &Path) -> io::Result<String> {
let mut f = File::open(path)?;
let mut s = String::new();
match f.read_to_string(&mut s) {
Ok(_) => Ok(s),
Err(e) => Err(e),
}
}
fn echo(s: &str, path: &Path) -> io::Result<()> {
let mut f = File::create(path)?;
f.write_all(s.as_bytes())
}
fn touch(path: &Path) -> io::Result<()> {
match OpenOptions::new().create(true).write(true).open(path) {
Ok(_) => Ok(()),
Err(e) => Err(e),
}
}
fn main() {
println!("`mkdir a`");
match fs::create_dir("a") {
Err(why) => println!("! {:?}", why.kind()),
Ok(_) => {},
}
println!("`echo hello > a/b.txt`");
echo("hello", &Path::new("a/b.txt")).unwrap_or_else(|why| {
println!("! {:?}", why.kind());
});
println!("`mkdir -p a/c/d`");
fs::create_dir_all("a/c/d").unwrap_or_else(|why| {
println!("! {:?}", why.kind());
});
println!("`touch a/c/e.txt`");
touch(&Path::new("a/c/e.txt")).unwrap_or_else(|why| {
println!("! {:?}", why.kind());
});
println!("`ln -s ../b.txt a/c/b.txt`");
#[cfg(target_family = "unix")] {
unix::fs::symlink("../b.txt", "a/c/b.txt").unwrap_or_else(|why| {
println!("! {:?}", why.kind());
});
}
#[cfg(target_family = "windows")] {
windows::fs::symlink_file("../b.txt", "a/c/b.txt").unwrap_or_else(|why| {
println!("! {:?}", why.to_string());
});
}
println!("`cat a/c/b.txt`");
match cat(&Path::new("a/c/b.txt")) {
Err(why) => println!("! {:?}", why.kind()),
Ok(s) => println!("> {}", s),
}
println!("`ls a`");
match fs::read_dir("a") {
Err(why) => println!("! {:?}", why.kind()),
Ok(paths) => for path in paths {
println!("> {:?}", path.unwrap().path());
},
}
println!("`rm a/c/e.txt`");
fs::remove_file("a/c/e.txt").unwrap_or_else(|why| {
println!("! {:?}", why.kind());
});
println!("`rmdir a/c/d`");
fs::remove_dir("a/c/d").unwrap_or_else(|why| {
println!("! {:?}", why.kind());
});
}