Построчное чтение большого файла и предотвращение ошибок 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 функция.

Другие вопросы по тегам