Построчное чтение большого файла и предотвращение ошибок utf8 в Rust
У меня действительно большой файл, который "должен" состоять из строк JSON. Однако когда я использую следующий код, я получаю сообщение "поток не содержит допустимого UTF8".
let file = File::open("foo.txt")?;
let reader = BufReader::new(file);
for line in reader.lines() {
println!("{}", line?);
}
Ok(())
Теперь ответ на этот вопрос - использовать Vec, а не String. Но весь код, который я видел,file.read_to_end(buf)
как ответ, который не сработает для файлов, с которыми мне приходится работать.
Я ищу, чтобы прочитать файл построчно, использовать преобразование utf8 с потерями, а затем выполнить некоторые вычисления и передать результат в другой файл.
1 ответ
Вы можете использовать BufReader's read_until
функция. Он очень похож на File'sread_to_end
, но также требует byte
аргумент-разделитель. Этот разделитель может быть любым байтом и новой строкой.\n
байт вам подойдет. После этого вы можете просто преобразовать буфер из UTF-8 с потерями. Это выглядело бы примерно так:
let file = File::open("foo.txt")?;
let mut reader = BufReader::new(file);
let mut buf = vec![];
while let Ok(_) = reader.read_until(b'\n', &mut buf) {
if buf.is_empty() {
break;
}
let line = String::from_utf8_lossy(&buf);
println!("{}", line);
buf.clear();
}
Ok(())
Конечно, это можно было бы абстрагировать в итераторе, как это делается Lines, но основная логика такая же, как и выше.
ПРИМЕЧАНИЕ: в отличие от lines
функция, результирующие строки будут включать символ новой строки и возврат каретки (\r
), если он есть. Эти символы необходимо будет удалить, если поведение решения должно соответствоватьlines
функция.