Rust 文件操作 - 读、写、删、查询属性

Rust 文件操作 - 读、写、删、查询属性

Rust 中主要围绕 std::fs::Filestd::path::{Path, PathBuf} 来实现文件相关的操作,前者完成文件创建与读写删等操作,后者完成文件路径的构造。

跟随本文流程操作一遍,就可以较好的掌握相关内容。

编写本文时,笔者使用的 Rust 版本为 1.79.0。


要操作文件,就先构造一个可用的路径

  • std::path::PathBufstd::path::Path

这俩都是用于构造文件路径的,开发中选取其中适合的一个即可。两者区别在于 PathBuf 构造的是可变路径,可以在后续通过 push() 来不断扩展路径,push() 会自动完成路径的拼接。

use std::path::PathBuf;

// 先构造路径缓存
let mut path = PathBuf::new();

// 后续补全整个路径
path.push(r"C:\");
path.push("windows");
path.push("system32");

// 这里官方示例使用 set_extension() 但实际上,在最后一次的 push 中,我们直接写 system32.dll
// 也是一样的效果
path.set_extension("dll");

// 最终路径: C:\\windows\\system32.dll

而 Path 需要在 new() 环节就确定整个完整的路径且不可再变。

use std::path::Path;
use std::ffi::OsStr;

// Note: this example does work on Windows
let path = Path::new("./foo/bar.txt");

let parent = path.parent();
assert_eq!(parent, Some(Path::new("./foo")));

let file_stem = path.file_stem();
assert_eq!(file_stem, Some(OsStr::new("bar")));

let extension = path.extension();
assert_eq!(extension, Some(OsStr::new("txt")));

只构造路径是无用的,我们还需要把路径“喂给”下面这位才可以实现文件的创建。


路径可用,我们开始操作文件

  • std::fs::File::create() 才是真正在干活的

File::create() 需要接收一个路径,可以是 String 或 &str、PathBuf、Path 等 ,返回 Result,可以通过 unwrap() 取出 File 结构,File 结构是我们操控文件的“句柄”

// main.rs
use std::fs::File;
use std::path::Path;

let save_path = Path::new(r"D:\code\rustProject\file_test\src\test.txt");
// 上边的代码你也可以写成
// let mut save_path = PathBuf::new();
// save_path.push(r"D:\code\rustProject\file_test\src");
// save_path.push("test.txt");
// 最终效果都是一致的
let mut file_handle = File::create(save_path).unwrap();

现在我们拿到了操作文件的“句柄”,那么可以开始操作文件了

写操作

如果需要写入 bytes ,如下载文件,则根据官方示例使用 Write trait 下的 write_all 方法。

// main.rs
use std::io::prelude::*;
use std::fs::File;

fn main() -> std::io::Result<()> {
    let mut buffer = File::create("foo.txt")?;

    buffer.write_all(b"some bytes")?;
    Ok(())
}

如果需要写入文本 ,如保存输入,则根据官方示例使用 write!() 宏。

// main.rs
use std::fs::File;
use std::path::Path;
// use std::path::PathBuf;
use std::io::Write;   // write!() 宏使用了该 Trait,遵循 Rust 语法(孤儿规则)必须引入该 Trait

fn main() {
    let save_path = Path::new(r"D:\code\rustProject\file_test\src\test.txt");
    // let mut save_path = PathBuf::new();
    // save_path.push(r"D:\code\rustProject\file_test\src");
    // save_path.push("test.txt");
    let mut file_handle = File::create(save_path).unwrap();
    write!(file_handle, "oh, My dear Rust~").unwrap();
}

上边的代码实现了在 D:\code\rustProject\file_test\src 位置下创建名为 test.txt 的文件,并写入内容 oh, My dear Rust~

注意!该创建文件的方式是覆盖式的,如果文件已经存在则会将文件内容完全抹去,再重头写入文本,如果你不想这样的话,你可以使用 File::create_new() 方法,该方法在创建文件时,如果遇到文件已存在的情况,会抛出 AlreadyExists 错误,具体请在编辑器中跳转至对应源码注释查看。

接下来我们尝试从 test.txt 中读取改文字并打印至控制台。

读操作

读取操作也是很简单的,通过 File::open() 打开我们刚才生成的文件再读取其内容即可,我们直接看代码。

use std::fs::File;
use std::path::Path;
use std::io::{Read, Write};

fn main() {
		// 文件路径构造
    let save_path = Path::new(r"D:\code\rustProject\file_test\src\test.txt");
    // 生成文件
    let mut file_handle = File::create(save_path).unwrap();
    write!(file_handle, "oh, My dear Rust~").unwrap();

		// 开始读取文件
    file_handle = File::open(save_path).unwrap();
    let mut text = String::new();   // 作为容纳读取结果的容器
    file_handle.read_to_string(&mut text).expect("读取失败");   // 读取文件内容
    println!("{text}");     // 打印出文件内容
}

最终输出结果:oh, My dear Rust~ ,读取文件成功。

删操作

在 Rust 中,我们可以通过 std::fs::remove_file() 方法来实现文件的删除。

实现代码如下,我们将在打印出文件内容后删除该文件。

注意!该删除方式会直接移除文件,不会将其移至回收站!

use std::fs::{File, remove_file};
use std::path::Path;
use std::io::{Read, Write};  // 这里新引入了 Read Trait,因为 read_to_string() 方法

fn main() {
    let save_path = Path::new(r"D:\code\rustProject\file_test\src\test.txt");
    let mut file_handle = File::create(save_path).unwrap();
    write!(file_handle, "oh, My dear Rust~").unwrap();

    file_handle = File::open(save_path).unwrap();
    let mut text = String::new();   // 作为容纳读取结果的容器
    file_handle.read_to_string(&mut text).expect("读取失败");   // 读取文件内容
    println!("{text}");     // 打印出文件内

    remove_file(save_path).unwrap()     // 仅此一行,删除 save_path 指定的文件
}

查询文件属性

文件自身是具有属性的,有时我们需要获取这些文件属性来进行下一步操作,必要时我们也可能回去修改它,如将文件变为仅允许读写。

我们直接看代码:

use std::time::SystemTime;   // 用于获取现在的系统时间
use std::fs::{File, remove_file};
use std::path::Path;
use std::io::{Read, Write};

fn main() {
    let save_path = Path::new(r"D:\code\rustProject\file_test\src\test.txt");
    let mut file_handle = File::create(save_path).unwrap();
    write!(file_handle, "oh, My dear Rust~").unwrap();

    let mut file_handle = File::open(save_path).unwrap();
    let mut text = String::new();   // 作为容纳读取结果的容器
    file_handle.read_to_string(&mut text).expect("读取失败");   // 读取文件内容
    println!("{text}");     // 打印出文件内

    println!("文件属性如下:");
    println!("因为我们在对刚生成的文件进行属性获取,牵涉时间的地方可能会得到 µs 级的信息!!!");
    // 单位可以自己换算,返回的是 bytes
    println!("文件大小:{:?} Bytes", file_handle.metadata().unwrap().len());
    // 在计算机中,文件夹也是一种文件,因此也可以使用上边的方法创建目录
    println!("该文件是不是文件夹这种特殊文件:{:?}", file_handle.metadata().unwrap().is_dir());
    // 这里意在获取文件权限,但目前 rust 标准库(rustc 1.79.0) 只支持获取文件是否可读。期待 rust 的进一步发展
    println!("该文件是否为只读:{:?}", file_handle.metadata().unwrap().permissions().readonly());
    // 创建的时间距现在多久
    println!("该文件创建的时间:{:?}", file_handle.metadata().unwrap().created().unwrap().duration_since(SystemTime::now()));
    // 最后修改距现在多久
    println!("最后一次修改时间距现在过去了:{:?}", file_handle.metadata().unwrap().modified().unwrap().duration_since(SystemTime::now()));
    // 最后访问距现在多久
    println!("最后一次访问的时间距现在过去了:{:?}", file_handle.metadata().unwrap().accessed().unwrap().duration_since(SystemTime::now()));

    remove_file(save_path).unwrap();     // 仅此一行
}

以上便是 Rust 1.79.0 全部可以直接获取的文件属性,可见,目前 rust 标准库对于文件属性获取方面还存在不足,可以直接获取的信息不多,但毕竟 rust 还年轻,请再多给它一些时间!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值