Есть ли символьный итератор поверх std.io.Reader?

Использовать str.form_utf8 не получится, т.к. весь огромный файл в память не лезет, а читать по строкам не имеет смысла, т.к. там нет переносов строк.
А Reader.chars у нас depricated.
Гуглопоиск в основном даёт ссылки на stackoverflow где по сути предлагают тот же str.form_utf8.

Code that does not care about processing data incrementally can use Read::read_to_string instead. Code that does care presumably also wants to control its buffering strategy and work with &[u8] and &str slices that are as large as possible, rather than one char at a time. It should be based on the str::from_utf8 function as well as the valid_up_to and error_len methods of the Utf8Error type. One tricky aspect is dealing with cases where a single char is represented in UTF-8 by multiple bytes where those bytes happen to be split across separate read calls / buffer chunks. ( Utf8Error::error_len returning None indicates that this may be the case.) The utf-8 crate solves this, but in order to be flexible provides an API that probably has too much surface to be included in the standard library.

С виду похоже на описание твоего случая. Т.е. читаешь по кускам в байтовый буфер нужного тебе размера, а потом при помощи utf-8 получаешь что-то максимально похожее на строку из этого дела. Главное ошибки “склейки” блоков корретно обрабатывать.

Ничего проще я тоже нагуглить не могу.

Это я читал.
Я думал может есть готовое, чтобы своё не велосипедить.

На StackOverflow есть такой вариант

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();
    }
}

Такое решение под изначальный вопрос вряд ли подходит.

Тогда можно использовать read() и читать нужное число байтов кратное 4, затем from_utf8_lossy -> trim_right_matches -> chars.

1 лайк

Хм, почему кратное четырем? Там же utf-8, а не utf32.
И зачем trim? И чем лучше варианта с utf-8 пакетом выше?

По ответу я решил, что это не подходит, хотя мой вариант получается сложнее. Разе UTF-8 не до 4 байт?

Я так понял что подходит, просто хотелось прям удобное и готовое решение, а не собирать самому из кусков.

До четырех, да, но я не понял как именно отбрасывание “мусорного” хвоста должно работать. Вроде бы trim_right_matches не про это же.

Читать файл нужно на сколько, сколько в буфер влезет, но в конце прочитанной строки в буфере, в пределах максимальной длинны UTF8, может отказаться часть байт недочитанного UTF8 символа.
которые нужно будет перед следующей заливкой буфера поставить в начало и, в место, оставшееся в буфере после них, дочитывать

1 лайк