Porównajmy 4 podejścia.
1. Read::chars
Można skopiować Read::chars
wdrożenia, ale jest oznaczone niestabilna z
semantykę częściowego odczytu/zapisu, gdzie błędy zdarzyć obecnie niejasne i mogą ulec zmianie
dlatego należy zachować ostrożność. W każdym razie wydaje się to najlepszym podejściem.
2. flat_map
flat_map
alternatywa nie kompiluje:
use std::io::{BufRead, BufReader};
use std::fs::File;
pub fn main() {
let mut f = BufReader::new(File::open("input.txt").expect("open failed"));
for c in f.lines().flat_map(|l| l.expect("lines failed").chars()) {
println!("Character: {}", c);
}
}
problemów jest to, że chars
pożycza od napisu, ale tylko l.expect("lines failed")
mieszka wewnątrz zamknięcia, więc kompilator daje błąd borrowed value does not live long enough
.
3. Zagnieżdżone dla
Ten kod
use std::io::{BufRead, BufReader};
use std::fs::File;
pub fn main() {
let mut f = BufReader::new(File::open("input.txt").expect("open failed"));
for line in f.lines() {
for c in line.expect("lines failed").chars() {
println!("Character: {}", c);
}
}
}
działa, ale utrzymuje alokacji ciąg dla każdej linii. Poza tym, jeśli w pliku wejściowym nie ma linii podziału, cały plik będzie ładowany do pamięci.
4.BufRead::read_until
Pamięć wydajny alternatywą Podejście 3 jest użycie Read::read_until
i korzystać z jednego łańcucha, aby przeczytać każdy wiersz:
use std::io::{BufRead, BufReader};
use std::fs::File;
pub fn main() {
let mut f = BufReader::new(File::open("input.txt").expect("open failed"));
let mut buf = Vec::<u8>::new();
while f.read_until(b'\n', &mut buf).expect("read_until failed") != 0 {
// this moves the ownership of the read data to s
// there is no allocation
let s = String::from_utf8(buf).expect("from_utf8 failed");
for c in s.chars() {
println!("Character: {}", c);
}
// this returns the ownership of the read data to buf
// there is no allocation
buf = s.into_bytes();
buf.clear();
}
}
Dla niektórych typów plików tekstowych. 'F.lines() flat_map (| l | l.chars()) '... ale to nie jest dobre rozwiązanie. –
Czy rozważałeś właśnie skopiowanie implementacji w międzyczasie? To tylko ~ 100 linii i oznacza, że twój kod będzie banalny do uaktualnienia, jeśli 'chars' będzie stabilne. – Veedrac