file - 如何在文件开头添加一行?

标签 file io rust

我正在尝试将新行添加到文本文件的开头。我首先使用 append 打开文件,但这只允许我使用 write_all 写入文件末尾,至少这是我得到的结果。如果我正确阅读文档,这是设计使然。

我试过使用 seek,但没有解决问题。

这是我目前拥有的:

let mut file = OpenOptions::new().append(true).open(&file_path).unwrap();
file.seek(SeekFrom::Start(0));
file.write_all(b"Cool days\n");

如果我使用 write 打开文件,我最终会覆盖数据而不是添加数据。使用 Rust 完成此任务的合适方法是什么?

最佳答案

您不能用任何编程语言直接执行此操作。在 C# 中查看关于同一主题的其他一些问题, Python , NodeJs , PHP , BashC .

有几种不同权衡的解决方案:

  1. 将整个文件复制到内存中,写入你想要的数据,然后写入文件的其余部分。如果文件很大,这可能是一个糟糕的解决方案,因为它会使用大量内存,但可能适合小文件,因为它实现起来很简单。

  2. 使用缓冲区,大小与您要添加的文本相同。一次将文件的 block 复制到内存中,然后用前一个 block 覆盖它。通过这种方式,您可以将文件的内容与开头的新文本一起打乱。这可能比其他方法慢,但不需要分配大量内存。当进程没有删除文件的权限时,它也可能是最佳选择。但要小心:如果进程被中断,这种方法可能会使文件处于损坏状态。

  3. 将新数据写入临时文件,然后附加原始文件的内容。然后删除原来的并重命名临时文件。这是一个很好的解决方案,因为它将繁重的工作委托(delegate)给了操作系统,并且备份了原始数据,因此如果进程中断也不会损坏。

通过在 Stack Overflow 上搜索,第三种解决方案似乎是其他语言最受欢迎的答案,例如in Bash .这可能是因为它快速、安全并且通常只需几行代码即可实现。

快速 Rust 版本看起来像这样:

extern crate mktemp;
use mktemp::Temp;
use std::{fs, io, io::Write, fs::File, path::Path};

fn prepend_file<P: AsRef<Path>>(data: &[u8], file_path: &P) -> io::Result<()> {
    // Create a temporary file 
    let mut tmp_path = Temp::new_file()?;
    // Stop the temp file being automatically deleted when the variable
    // is dropped, by releasing it.
    tmp_path.release();
    // Open temp file for writing
    let mut tmp = File::create(&tmp_path)?;
    // Open source file for reading
    let mut src = File::open(&file_path)?;
    // Write the data to prepend
    tmp.write_all(&data)?;
    // Copy the rest of the source file
    io::copy(&mut src, &mut tmp)?;
    fs::remove_file(&file_path)?;
    fs::rename(&tmp_path, &file_path)?;
    Ok(())
}

用法:

fn main() -> io::Result<()> {
    let file_path = Path::new("file.txt");
    let data = "Data to add to the beginning of the file\n";
    prepend_file(data.as_bytes(), &file_path)?;
    Ok(())
}

关于file - 如何在文件开头添加一行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43441166/

相关文章:

c - C中从文件到结构

java - 如何将文件与 String java 中的文件完全一样保存

scala - 仅使用 IO monad 中的值,无需先行 IO 操作

c++ - 我应该让 QFile (或 fstream)保持打开状态吗?

ruby - 在 Ruby 中编辑文件中的每一行

asp.net - 读取 Gedcom 文件并存储在数据库中

rust - 如何将std::sync::mpsc::Sender <T>传递给warp中的处理程序?

rust - Rc<RefCell<T>> 和 RefCell<Rc<T>> 有什么区别?

rust - 如何将具有 `Read`特征的字符串形式的东西传递给 `From`的实现?

java - 如何在 adf mobile 中创建文件