Rust 中的文件操作示例详解

 更新时间:2021年11月11日 10:38:03   作者:花落花开99  
Rust 中的路径操作是跨平台的,std::path 模块提供的了两个用于描述路径的类型,本文给大家介绍Rust 中的文件操作示例详解,感兴趣的朋友一起看看吧

文件路径

想要打开或者创建一个文件,首先要指定文件的路径。

Rust 中的路径操作是跨平台的,std::path 模块提供的了两个用于描述路径的类型:

  1. PathBuf – 具有所有权并且可被修改,类似于 String
  2. Path – 路径切片,类似于 str

示例

use std::path::Path;
use std::path::PathBuf;
fn main() {
    // 直接将一个字符串切片包装成一个路径切片
    let path = Path::new("./foo/bar.txt");

    // 返回上级路径,若无上级路径则返回 `None`
    let parent = path.parent().unwrap();

    // 返回文件名(不包含文件扩展名)
    let file_stem = path.file_stem().unwrap();

    println!(
        "path: {:?}, parent: {:?}, file_stem: {:?}",
        path, parent, file_stem
    );

    // 创建一个空的 `PathBuf`
    let mut empty_path = PathBuf::new();
    println!("empty_path: {:?}", empty_path);

    // 根据字符串切片创建 `PathBuf`
    let path = PathBuf::from(r"C:\windows\system32.dll");

    // 添加路径
    empty_path.push(r"C:\");

    println!("empty_path: {:?}, path: {:?}", empty_path, path);
}

文件创建和删除

Rust 的 std::fs 模块提供了一系列文件系统操作的功能。

目录创建和删除

创建目录的函数:

  • create_dir<P: AsRef<Path>>(path: P) -> Result<()> – 创建一个空目录,若指定路径不存在则会返回错误
  • create_dir_all<P: AsRef<Path>>(path: P) -> Result<()> – 级联创建目录。

示例

use std::fs;
// 由于字符串切片实现了 `AsRef<Path>` Trait,因此函数中的参数可以直接使用字符串字面量
fn main() -> std::io::Result<()> {
    // 创建一个空目录
    fs::create_dir("./empty")?;

    // 创建一个目录,若其上级目录不存在,则一同创建
    fs::create_dir_all("./some/dir")?;

    Ok(())
}

删除目录的函数:

  • remove_dir<P: AsRef<Path>>(path: P) -> Result<()> – 删除指定空目录。
  • remove_dir_all<P: AsRef<Path>>(path: P) -> Result<()> – 删除指定目录及其目录下的内容。

示例

use std::fs;

fn main() -> std::io::Result<()> {
    // 删除一个空目录
    fs::remove_dir("./empty")?;

    // 删除指定目录及其目录下的内容,但不会删除其上级目录
    fs::remove_dir_all("./some/dir")?;

    Ok(())
}

文件创建和删除

Rust 使用 std::fs::File 结构体与文件系统中的文件相关联,通过 std::fs::File 实例可以对文件进行读取和写入。

文件创建和删除的函数:

  • create<P: AsRef<Path>>(path: P) -> Result<File>
  • std::fs::remove_file<P: AsRef<Path>>(path: P) -> Result<()>

示例

use std::fs;
use std::fs::File;

fn main() -> std::io::Result<()> {
    // 以只写模式打开指定文件,若文件存在则清空文件内容,若文件不存在则新建一个
    let mut f = File::create("foo.txt")?;

    // 删除文件
    fs::remove_file("foo.txt")?;

    Ok(())
}

文件读取和写入

std::fs::File 本身实现了 ReadWrite Trait,所以文件的读写非常简单。

文件打开

在读写文件之前,首先应该得到一个 File 类型实例。除了可以在创建文件时获取 File 实例,还可以使用 Fileopen 函数:

  • open<P: AsRef<Path>>(path: P) -> Result<File>

示例

use std::fs::File;

fn main() -> std::io::Result<()> {
    // 以只读模式打开指定文件,若文件不存在则返回错误
    let _file = File::open("foo.txt")?;

    Ok(())
}

使用 createopen 函数获取的 File 实例是只读或者只写的,如果想要控制更多的读写选项,则需要使用 std::fs::OpenOptions。它是一个 Builder,createopen 函数的底层也是这个 Builder。

使用 std::fs::OpenOptions 时,首先调用 OpenOptions::new,然后通过链式调用来设置读写选项,最后调用 OpenOptions::open 打开指定的文件。

示例

use std::fs::OpenOptions;

fn main() -> std::io::Result<()> {
    let _file = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true) // 新建,若文件存在则打开这个文件
        .open("foo.txt")?;

    let _file = OpenOptions::new()
        .append(true) // 追加内容
        .open("foo.txt")?;

    let _file = OpenOptions::new()
        .write(true)
        .truncate(true) // 清空文件
        .open("foo.txt");

    Ok(())
}

文件读取

读取文件主要用的是 std::io::Read Trait 中的函数。比如:

  • read(&mut self, buf: &mut [u8]) -> Result<usize>
  • read_to_string(&mut self, buf: &mut String) -> Result<usize>

示例

use std::fs::File;
use std::io;
// `prelude` 模块包含通常使用的 IO Trait: `BufRead`, `Read`, `Write`, `Seek`
use std::io::prelude::*;

fn main() -> io::Result<()> {
    let mut f = File::open("foo.txt")?;
    let mut buffer = [0; 10];
    // 读取文件中的前10个字节
    let n = f.read(&mut buffer[..])?;
    println!("The bytes: {:?}", &buffer[..n]);

    // 接着读取10个字节
    let n = f.read(&mut buffer[..])?;
    println!("The bytes: {:?}", &buffer[..n]);

    let mut f = File::open("foo.txt")?;
    let mut buffer = String::new();
    // 读取文件所有内容并转为字符字符串,若文件非 UTF-8 格式,则会报错
    f.read_to_string(&mut buffer)?;
    println!("The string: {}", buffer);

    Ok(())
}

另外,File 类型还实现了 std::io::Seek Trait,Seek 主要提供了一个 seek 函数,可以控制文件读取和写入的起始位置。

  • seek(&mut self, pos: SeekFrom) -> Result<u64>

示例

use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::io::SeekFrom;

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

    // 将游标前移 10 个字节(游标的默认位置是 0)
    f.seek(SeekFrom::Start(10))?;

    // 将前 10 个字节之后的内容读取到 Buf 中
    let mut buffer = String::new();
    f.read_to_string(&mut buffer)?;
    println!("The string: {}", buffer);

    Ok(())
}

除了可以设置文件读取的起点,还可以限制文件读取的长度。std::io::Read 提供了 take 函数来限制文件读取的长度。

  • take(self, limit: u64) -> Take<Self>

示例

use std::fs::File;
use std::io;
use std::io::prelude::\*;

fn main() -> io::Result<()> {
let f = File::open("foo.txt")?;
let mut buffer = [0; 10];

    // 限制读取长度最多为 5 字节
    let mut handle = f.take(5);

    handle.read(&mut buffer)?;
    println!("buffer: {:?}", buffer);

    Ok(())

}

文件写入

读取文件主要用的是 std::io::Write Trait 中的函数。比如:

  • fn write(&mut self, buf: &[u8]) -> Result<usize> – 尝试将 Buf 中的全部内容写入文件,有可能不成功。
  • fn flush(&mut self) -> Result<()>
  • fn write_all(&mut self, buf: &[u8]) -> Result<()> – 持续调用 write,将 Buf 中的所有内容都写入文件。

示例

use std::fs::File;
use std::io::prelude::*;

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

    buffer.write(b"some bytes")?;

    buffer.write_all(b"more bytes")?;

    buffer.flush()?;

    Ok(())
}

相关资料

The Rust Standard Library

Rust By Example

RustPrimer

到此这篇关于Rust 中的文件操作的文章就介绍到这了,更多相关Rust 文件操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • rust解决嵌套——Option类型的map和and_then方法的使用

    rust解决嵌套——Option类型的map和and_then方法的使用

    这篇文章主要介绍了rust解决嵌套——Option类型的map和and_then方法,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-02-02
  • Rust 中判断两个 HashMap 是否相等

    Rust 中判断两个 HashMap 是否相等

    在Rust标准库中,HashMap 实现了 PartialEq 和 Eq trait,但是这些trait的实现是基于严格的结构相等性,包括元素的顺序,这篇文章主要介绍了Rust 中判断两个 HashMap 是否相等,需要的朋友可以参考下
    2024-04-04
  • 一文掌握Rust编程中的生命周期

    一文掌握Rust编程中的生命周期

    在Rust语言中, 每一个引用都有其生命周期, 通俗讲就是每个引用在程序执行的过程中都有其自身的作用域, 一旦离开其作用域, 其生命周期也宣告结束, 值不再有效,这篇文章主要介绍了Rust编程中的生命周期,需要的朋友可以参考下
    2023-11-11
  • Rust语言中的哈希表

    Rust语言中的哈希表

    哈希表也是集合中的一种,也是最常用的集合形式,目前Rust语言核心部分没有对哈希表进行实现,是使用标准库提供的,这篇文章主要介绍了Rust语言之哈希表,需要的朋友可以参考下
    2024-02-02
  • Rust个人学习小结之Rust的循环

    Rust个人学习小结之Rust的循环

    这篇文章主要介绍了Rust个人学习小结之Rust的循环,今天主要了解了Rust语言的3种循环方法: loop、while、for,本文结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-01-01
  • Rust使用kind进行异常处理(错误的分类与传递)

    Rust使用kind进行异常处理(错误的分类与传递)

    Rust 有一套独特的处理异常情况的机制,它并不像其它语言中的 try 机制那样简单,这篇文章主要介绍了Rust指南错误的分类与传递以及使用kind进行异常处理,需要的朋友可以参考下
    2022-09-09
  • Rust duckdb和polars读csv文件比较情况

    Rust duckdb和polars读csv文件比较情况

    duckdb在数据分析上,有非常多不错的特质,1、快;2、客户体验好,特别是可以同时批量读csv在一个目录下的csv等文件,今天来比较下Rust duckdb和polars读csv文件比较的情况,感兴趣的朋友一起看看吧
    2024-06-06
  • Rust日期与时间的操作方法

    Rust日期与时间的操作方法

    Rust的时间操作主要用到chrono库,接下来我将简单选一些常用的操作进行介绍,感兴趣的朋友跟随小编一起看看吧
    2023-09-09
  • 使用Rust语言管理Node.js版本

    使用Rust语言管理Node.js版本

    这篇文章主要介绍一个使用 Rust 进行编写的一体化版本管理工具 Rtx,比如使用它来管理 Node.js 版本,它很简单易用,使用了它,就可以抛弃掉 nvm 了,文中通过代码示例给大家介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • Rust 语言的全链路追踪库 tracing使用方法

    Rust 语言的全链路追踪库 tracing使用方法

    这篇文章主要介绍了Rust 语言的全链路追踪库 tracing,接下来就以 tracing 为例,介绍一下trace 的核心概念以及使用方法,需要的朋友可以参考下
    2022-12-12

最新评论