Считайте весь текстовый файл в память, затем обработайте его построчно без выделения/копирования

Предположим, мы прочитали содержимое текстового файла в stringstream через

std::ifstream file(filepath);
std::stringstream ss;
ss << file.rdbuf();

и теперь хотите обработать файл построчно. Это можно сделать через

for (std::string line; std::getline(ss, line);)
{
}

Однако, учитывая, что ss содержит все содержимое файла во внутреннем буфере (и что мы можем получить это содержимое как string через ss.str()), приведенный выше код крайне неэффективен. Для каждой строки файла выполняется выделение памяти и операция копирования.

Можно ли придумать решение, которое предоставляет lines в форме std::string_view? (Вы можете использовать другой механизм для загрузки всего файла; мне не нужен доступ к нему через stringstream.)


person 0xbadf00d    schedule 06.04.2018    source источник
comment
en.cppreference.com/w/cpp/regex/basic_regex может оказаться полезным .   -  person Clearer    schedule 07.04.2018
comment
Делать это таким образом не очень неэффективно. Это было хешировано на протяжении многих лет.   -  person Jive Dadson    schedule 07.04.2018
comment
Что произойдет, если не хватит памяти для хранения всего файла в памяти?   -  person Thomas Matthews    schedule 07.04.2018
comment
Действительно ли программе действительно нужен весь файл в памяти сразу? Большинство программ считывают данные из файла и больше не используют их; таким образом, они могут читать запись за раз. Текстовые редакторы — это другое животное.   -  person Thomas Matthews    schedule 07.04.2018
comment
Найдите в Интернете файлы с отображением памяти.\   -  person Thomas Matthews    schedule 07.04.2018
comment
Или прочитайте man 2 mmap. (с приведенным примером C)   -  person David C. Rankin    schedule 07.04.2018
comment
Вы создаете переменную line только один раз, а затем повторно используете ее. В чем проблема?   -  person Bo Persson    schedule 07.04.2018


Ответы (1)


приведенный выше код крайне неэффективен. Для каждой строки файла выполняется выделение памяти и операция копирования.

Можно ли придумать решение, предоставляющее строки в виде std::string_view?

Нет, насколько я знаю.

Но вы можете использовать метод getline() в stringstream, который получает указатель на char.

Что-то вроде (осторожно: код не проверен)

constexpr std::size_t dim { 100U }; // choose you the dim

char buff[dim];

while ( ss.getline(buff, dim) )
 {
   // do something
 }

Копия остается, но, по крайней мере, таким образом вы должны избежать - для каждой строки - распределения.

person max66    schedule 06.04.2018
comment
std::string также будет повторно использовать свой внутренний буфер и перераспределять только в том случае, если вы получите строку намного длиннее, чем кто-либо раньше. - person Bo Persson; 07.04.2018