文件是一个字节序列.由于性能原因,文件几乎总是占据一个硬盘驱动器上的空间块.从程序员的角度来看,操作连续文件也更容易,因为在这种情况下,文件可以被认为是一个普通的数组; 否则应该有一些链表式或类似树的数据结构,在99%的情况下只会使编程更难.因此,可以轻松地附加文件,但在中间插入或删除数据更难.这通常分五步完成(插入;删除非常相似):
替换可能不同长度的单词通常涉及移除或插入.对于大小合适的文件,最简单的方法是将整个源文件读入内存,对其运行替换操作并将结果转储回原始文件.这样,项目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操作,将结果写入临时文件.处理完整个源文件后,临时文件将在其上移动.如果读取大于单字节的块,则还需要处理在这些块之间"拆分"的单词时的情况.
| 归档时间: |
|
| 查看次数: |
1319 次 |
| 最近记录: |