在文件开头添加行 [英] Prepend line to beginning of file

查看:101
本文介绍了在文件开头添加行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to add a new line to the beginning of a text file. I start by opening the file with append but that only allows me to use write_all to write to the end of the file, at least that's the result I'm getting. If I read the documentation correctly, this is by design.

我尝试过玩seek,但这并不能解决问题.

I've tried to play with seek, but that didn't solve it.

这是我目前拥有的:

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实现此目标的合适方法是什么?

If I open the file with write, I end up overriding data instead of adding. What would be the appropriate way to go about accomplishing this with Rust?

推荐答案

您不能直接使用任何编程语言来执行此操作.在 C# Python PHP C .

You can't do this directly in any programming language. See some other questions on the same topic in C#, Python, NodeJs, PHP, Bash and C.

有几种折衷方案:

  1. 将整个文件复制到内存中,写入所需的数据,然后在其后写入文件的其余部分.如果文件很大,则由于它将使用的内存量,这可能是一个不好的解决方案,但由于易于实现,因此可能适合于小文件.

  1. Copy the entire file into memory, write the data you want, and then write the rest of the file after it. If the file is large, this might be a bad solution because of the amount of memory it will use, but might be suitable for small files, because it is simple to implement.

使用缓冲区,其大小与要添加的文本相同.一次将文件大块复制到内存中,然后用上一个大块覆盖.通过这种方式,您可以将文件的内容与新的文本一起放在开头,重新排列文件的内容.这可能比其他方法要慢,但是不需要大量的内存分配.当进程无权删除文件时,这也可能是最佳选择.但请注意:如果该过程被中断,此方法可能会使文件处于损坏状态.

Use a buffer, the same size as the text you want to prepend. Copy chunks of the file at a time into memory and then overwrite it with the previous chunk. In this way, you can shuffle the contents of the file along, with the new text at the start. This is likely to be slower than the other approaches, but will not require a large memory allocation. It could also be the best choice when the process doesn't have permission to delete the file. But be careful: If the process is interrupted, this approach could leave the file in a corrupted state.

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

Write the new data to a temporary file and then append the contents of the original. Then delete the original and rename the temporary file. This is a good solution because it delegates the heavy lifting to the operating system, and the original data is backed up so will not be corrupted if the process is interrupted.

通过搜索Stack Overflow,第三种解决方案似乎是其他语言(例如,其他语言)最受欢迎的答案.

From searching on Stack Overflow, the third solution seems to be the most popular answer for other languages, e.g. in Bash. This is likely to be because it is fast, safe and can often be implemented in just a few lines of code.

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

A quick Rust version looks something like this:

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(())
}

这篇关于在文件开头添加行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆