• Rust写文件的四种方式
  • 发布于 1周前
  • 21 热度
    0 评论
所有软件都必须在某个时刻向文件系统写入数据。对于用Rust编写的程序也是如此。日志消息需要持久化(只要它们不只是写入标准输出),并且需要保存数据以供以后使用,否则就会发生其他情况。当然,写数据与读数据是相反的。

在Rust中,有多种方法可以处理将数据写入文件的问题。其中一些方法比其他方法更容易,但都有它们的理由。有时你希望直接将文本写入文件,有时你希望写入某种二进制格式。无论你的用例是什么,Rust都能有一种方法来处理它。

在本文中,将介绍在Rust中编写文件的常用方法。
一,使用fs:write 一次将所有数据写入文件
通常的情况是持久化内存中已有的数据。一次写入所有数据,无论数据是字符串还是二进制格式都无关紧要。此外,如果文件还不存在,还可以创建一个文件。

这种方法的优点是:
1.使用方便
2.它仅仅是一行代码
3.fs:write会为您处理好一切
这种方法也有一些缺点:
1.它总是覆盖文件
2.它的性能在很大程度上取决于数据的大小——写入的数据越多,所需的时间就越长。

下面的代码是一次将所有数据写入文件的示例:
use std::fs;

fn write_string_to_file(path: &str, data: &str) -> Result<(), Box<dyn std::error::Error>> {
    fs::write(path, data)?;
    Ok(())
}

fn write_data_to_file(path: &str, data: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
    fs::write(path, data)?;
    Ok(())
}
二,使用fs::File API一次将所有数据写入文件
上面的方法只是这个方法的一个方便的包装,fs::File对如何处理文件及其内容有了更多的控制。这里唯一的区别是没有方便的底层将string转换为二进制。在这种情况下,就需要自己来转换。
这种方法的优点:
1.它使用起来仍然很方便
2.它只需要几行代码,这取决于你如何实现它
3.它可以灵活地扩展和更改
它的缺点包括:
1.它总是覆盖文件-没有追加
2.它的性能在很大程度上取决于数据的大小——写入的数据越多,所需的时间就越长

下面的代码是这种方法的示例:
use std::{fs, io::Write};

fn write_string_to_file(path: &str, data: &str) -> Result<(), Box<dyn std::error::Error>> {
    let mut file = fs::File::create(path)?;
    // 堆代码 duidaima.com
    // 你需要自己处理转换,可以尝试一次写入所有数据
    file.write_all(&data.as_bytes())?;

    // 或者尽量多写,但需要自己处理剩下的字节
    let remaining = file.write(&data.as_bytes())?;

    if remaining > 0 {
      // 处理剩下的字节
    }

    Ok(())
}

fn write_data_to_file(path: &str, data: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
    let mut file = fs::File::create(path)?;

    file.write_all(&data)?;

    let remaining = file.write(&data)?;

    if remaining > 0 {
    }

    Ok(())
}
三,向文件追加数据
如果要向现有文件追加数据,有一种方便的方法。使用fs::OpenOptions,可以对文件的打开方式进行细粒度控制。
这种方法的优点:
1.可以完全控制文件的处理方式
2.只需要几行代码
3.性能取决于写入的数据大小

这种方法的缺点:
1.每个调用都是潜在的系统调用
2.每次调用都会写入文件系统,如果数据大小不是最优的,那么这样做的代价可能会很高

下面的代码是这种方法的示例:
use std::{fs, io::Write};

fn append_string_to_file(path: &str, data: &str) -> Result<(), Box<dyn std::error::Error>> {
    let mut file = fs::OpenOptions::new().create(true).append(true).open(&path)?;

    // 你需要自己处理转换,可以尝试一次写入所有数据
    file.write_all(&data.as_bytes())?;

    // 或者尽量多写,但需要自己处理剩下的字节
    let remaining = file.write(&data.as_bytes())?;

    if remaining > 0 {
    }

    Ok(())
}

fn append_data_to_file(path: &str, data: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
    let mut file = fs::OpenOptions::new().create(true).append(true).open(&path)?;

    file.write_all(&data)?;

    let remaining = file.write(&data)?;

    if remaining > 0 {
    }

    Ok(())
}
四,用BufWriter向文件写入和追加数据
以前提出的所有方法都有一个共同点:它们总是立即写入给它们的所有内容,并且没有灵活性。有一种方法,在不影响程序性能的情况下一致地写入大块数据,可以使用BufWriter。在内部,BufWriter缓冲接收到的数据,并优化将数据写入文件系统的方式。这种方法不需要很多新概念,甚至还使用了上面已经学习过的api。

这种方法的优点:
1.可以完全控制文件的处理方式
2.它给你很大的灵活性
3.BufWriter在底层优化对文件系统的访问

这种方法的缺点:
1.使用起来可能有点困难
2.它需要更多的代码来实现

下面的代码是这种方法的示例:
use std::fs;
use std::io::{BufWriter, Write};

fn append_string_to_file(path: &str, data: &str) -> Result<(), Box<dyn std::error::Error>> {
    let file = fs::OpenOptions::new().create(true).append(true).open(&path)?;
    let mut file = BufWriter::new(file);

    file.write_all(&data.as_bytes())?;

    let remaining = file.write(&data.as_bytes())?;
    if remaining != 0 {

    }

    // 绝对明确的刷新buffwriter
    file.flush()?;

    Ok(())
}

fn append_data_to_file(path: &str, data: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
    let file = fs::OpenOptions::new().create(true).append(true).open(&path)?;
    let mut file = BufWriter::new(file);

    file.write_all(&data)?;

    let remaining = file.write(&data)?;
    if remaining != 0 {
    }

    file.flush()?;

    Ok(())
}
总结
在开发软件时,经常需要将数据写入文件。在本文中,介绍了用Rust写文件的四种不同方法。一次写入所有数据是用尽可能少的代码执行操作的好方法。此外,不必过于担心数据的格式。不过,这种便利是有代价的。需要写入的数据越多,内存就越大,而且现有文件会被覆盖。

使用File API一次写入所有数据是将所有数据转储到文件系统的另一种方法。与它的包装器API不同,它在处理此过程方面提供了更大的灵活性。此外,处理大量数据的问题仍然存在,大量的数据意味着大量的内存。

使用OpenOptions API向文件追加数据带来了比以前所有方法更大的灵活性。在这里,不必担心数据的大小。可以在处理文件时将数据附加到文件中,并且可以保持较低的内存配置。不过,这种方法需要进行一些微调。追加数据通常会导致系统调用,这些调用有时非常昂贵,因此仍有改进的空间。

最后,使用BufWriter提供了最大的灵活性,但它也是执行写操作的一种相对底层的方法。BufWriter本身至少会缓冲数据,但其有效性取决于使用的情况。

用户评论