如何替换.txt文件中的单词

use*_*152 3 rust

我想打开一个文件并在其中只替换一个单词.除了通过使用新文本创建新文件之外,我似乎无法找到任何方法.

Vla*_*eev 9

文件是一个字节序列.由于性能原因,文件几乎总是占据一个硬盘驱动器上的空间块.从程序员的角度来看,操作连续文件也更容易,因为在这种情况下,文件可以被认为是一个普通的数组; 否则应该有一些链表式或类似树的数据结构,在99%的情况下只会使编程更难.因此,可以轻松地附加文件,但在中间插入或删除数据更难.这通常分五步完成(插入;删除非常相似):

  1. 创建一个新的临时文件(或者,如果文件大小适中,在内存中创建一个缓冲区)
  2. 将插入点之前的所有内容复制到此新文件
  3. 将新数据写入此新文件或
  4. 将插入点后的所有内容复制到新文件
  5. 复制完所有内容后,将移动临时文件以替换原始文件

替换可能不同长度的单词通常涉及移除或插入.对于大小合适的文件,最简单的方法是将整个源文件读入内存,对其运行替换操作并将结果转储回原始文件.这样,项目2-4将由库代码自动为您完成字符串操作.这是一个示例程序(它从命令行参数获取源字,替换字和文件路径):

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

fn main() {
    // Handle errors
    run().unwrap();
}

fn run() -> Result<(), io::Error> {
    // Extract words and file path from the command line args
    let args: Vec<String> = env::args().skip(1).collect();
    if args.len() != 3 {
        println!("Wrong number of arguments");
        return Ok(());
    }

    let word_from = &args[0];
    // If the source word is empty then there is nothing to replace
    if word_from.is_empty() { return Ok(()); }  

    let word_to = &args[1];

    let file_name = &args[2];
    let file_path = Path::new(&file_name);

    // Open and read the file entirely
    let mut src = File::open(&file_path)?;
    let mut data = String::new();
    src.read_to_string(&mut data)?;
    drop(src);  // Close the file early

    // Run the replace operation in memory
    let new_data = data.replace(&*word_from, &*word_to);

    // Recreate the file and dump the processed contents to it
    let mut dst = File::create(&file_path)?;
    dst.write(new_data.as_bytes())?;

    println!("done");

    Ok(())
}
Run Code Online (Sandbox Code Playgroud)

请注意,创建临时文件仍然是一个好主意,因为将大块数据写入文件不是原子操作,而重命名文件通常是.因此,如果出现问题并且您不使用临时文件,您的源文件可能会损坏.如果您使用临时文件,则源文件将被完全替换或不被替换.

如果您的文件很大(即几千兆字节或更大),则流式替换可能是一个好主意.在这种情况下,您需要以块的形式读取文件(长度减少到1个字节,这可能会更容易)并在这些块中运行replace操作,将结果写入临时文件.处理完整个源文件后,临时文件将在其上移动.如果读取大于单字节的块,则还需要处理在这些块之间"拆分"的单词时的情况.