String 如何逐行读取文件,消除重复项,然后写回同一个文件?
我想读取一个文件,消除所有重复的内容,然后将其余内容写回文件中,就像一个重复的清洁器一样。 Vec,因为普通数组的大小是固定的,但my.txt是灵活的(我这样做对吗?) 读取,Vec中的行+删除副本: 缺少对文件的回写String 如何逐行读取文件,消除重复项,然后写回同一个文件?,string,file,rust,duplicate-removal,String,File,Rust,Duplicate Removal,我想读取一个文件,消除所有重复的内容,然后将其余内容写回文件中,就像一个重复的清洁器一样。 Vec,因为普通数组的大小是固定的,但my.txt是灵活的(我这样做对吗?) 读取,Vec中的行+删除副本: 缺少对文件的回写 use std::io; fn main() { let path = Path::new("test.txt"); let mut file = io::BufferedReader::new(io::File::open(&path, R));
use std::io;
fn main() {
let path = Path::new("test.txt");
let mut file = io::BufferedReader::new(io::File::open(&path, R));
let mut lines: Vec<String> = file.lines().map(|x| x.unwrap()).collect();
// dedup() deletes all duplicates if sort() before
lines.sort();
lines.dedup();
for e in lines.iter() {
print!("{}", e.as_slice());
}
}
使用std::io;
fn main(){
让path=path::new(“test.txt”);
让mut file=io::BufferedReader::new(io::file::open(&path,R));
让mut行:Vec=file.lines().map(|x | x.unwrap()).collect();
//重复数据消除()删除所有重复项,如果排序()在
line.sort();
行。重复数据消除();
对于e-in-line.iter(){
打印!(“{}”,例如as_slice());
}
}
读+写文件(未经测试,但我想应该可以工作)。
由于没有BufferedReader(或者我做错了其他事情,这也是一个很好的机会),Vec的行丢失了
使用std::io;
fn main(){
让path=path::new(“test.txt”);
让mut file=match io::file::open_模式(&path,io::open,io::ReadWrite){
Ok(f)=>f,
Err(e)=>panic!(“文件错误:{}”,e),
};
让mut行:Vec=file.lines().map(|x | x.unwrap()).collect();
line.sort();
//重复数据消除()删除所有重复项,如果排序()在
行。重复数据消除();
对于e-in-line.iter(){
写入(“{}”,e);
}
}
所以。。。。我怎样才能把这两个结合起来呢?:) 最终,您将遇到一个问题:您正试图写入正在读取的同一个文件。在这种情况下,它是安全的,因为您将读取整个文件,因此在读取之后不需要它。但是,如果您确实尝试写入文件,您会看到打开文件进行读取不允许写入!下面是执行此操作的代码:
use std::{
fs::File,
io::{BufRead, BufReader, Write},
};
fn main() {
let mut file = File::open("test.txt").expect("file error");
let reader = BufReader::new(&mut file);
let mut lines: Vec<_> = reader
.lines()
.map(|l| l.expect("Couldn't read a line"))
.collect();
lines.sort();
lines.dedup();
for line in lines {
file.write_all(line.as_bytes())
.expect("Couldn't write to file");
}
}
您可以打开文件进行读写操作:
use std::{
fs::OpenOptions,
io::{BufRead, BufReader, Write},
};
fn main() {
let mut file = OpenOptions::new()
.read(true)
.write(true)
.open("test.txt")
.expect("file error");
// Remaining code unchanged
}
但是你会看到(a)输出被追加,(b)所有新行在新行中丢失,因为BufRead
没有包含它们
我们可以将文件指针重置回起始位置,但随后可能会在末尾留下尾随内容(重复数据消除可能写入的字节数少于读取的字节数)。只需重新打开文件进行写入就更容易了,这将截断文件。另外,让我们使用一套数据结构来为我们执行重复数据消除
use std::{
collections::BTreeSet,
fs::File,
io::{BufRead, BufReader, Write},
};
fn main() {
let file = File::open("test.txt").expect("file error");
let reader = BufReader::new(file);
let lines: BTreeSet<_> = reader
.lines()
.map(|l| l.expect("Couldn't read a line"))
.collect();
let mut file = File::create("test.txt").expect("file error");
for line in lines {
file.write_all(line.as_bytes())
.expect("Couldn't write to file");
file.write_all(b"\n").expect("Couldn't write to file");
}
}
效率较低但较短的解决方案是将整个文件作为一个字符串读取,并使用str::lines
:
use std::{
collections::BTreeSet,
fs::{self, File},
io::Write,
};
fn main() {
let contents = fs::read_to_string("test.txt").expect("can't read");
let lines: BTreeSet<_> = contents.lines().collect();
let mut file = File::open("test.txt").expect("can't create");
for line in lines {
writeln!(file, "{}", line).expect("can't write");
}
}
使用std::{
集合::b树集,
fs::{self,File},
io::写,
};
fn main(){
让contents=fs::读取到字符串(“test.txt”).expect(“无法读取”);
let line:BTreeSet=contents.lines().collect();
让mut file=file::open(“test.txt”).expect(“无法创建”);
排队{
writeln!(文件“{}”,行)。预期(“无法写入”);
}
}
另见:
BTreeSet
而不是HashSet
(和。into iter()
而不是。drain()
)将对行进行排序。
% cat test.txt
a
a
b
a
a
b
a
b
% cargo run
% cat test.txt
a
b
use std::{
collections::BTreeSet,
fs::{self, File},
io::Write,
};
fn main() {
let contents = fs::read_to_string("test.txt").expect("can't read");
let lines: BTreeSet<_> = contents.lines().collect();
let mut file = File::open("test.txt").expect("can't create");
for line in lines {
writeln!(file, "{}", line).expect("can't write");
}
}