Чтение большого txt эффективно в С++

Мне нужно прочитать большой текстовый файл ( > 10 ГБ) на С++. Это файл csv с переменными длинными строками. когда я пытаюсь читать по строкам, используя ifstream, он работает, но занимает много времени, я думаю, это связано с тем, что каждый раз, когда я читаю строку, она переходит на диск и читает, что делает ее очень медленной.

Есть ли способ читать в буферах, например, читать 250 МБ на одном снимке (используя метод чтения ifstream), а затем получать строки из этого буфера, я вижу много проблем с решением, например буфером, может иметь неполные строки и т.д..

Есть ли решение для этого в С++, которое обрабатывает все эти случаи и т.д. Существуют ли библиотеки с открытым исходным кодом, которые могут это сделать, например boost и т.д.

Примечание. Я бы хотел избежать указателей FILE * и т.д.

Ответ 1

Попробуйте использовать функцию отображения отображаемой памяти Windows. Вызовы буферизуются, и вы можете обращаться с файлом, как с его простой памятью. отображенные карты памяти

Ответ 2

IOstream уже используют буферы так же, как вы описали (хотя обычно это всего несколько килобайт, а не сотни мегабайт). Вы можете использовать pubsetbuf, чтобы заставить его использовать больший буфер, но я бы не ожидал каких-либо огромных выигрышей. Большая часть накладных расходов в IO-потоках связана с другими областями (например, с использованием виртуальных функций), а не из-за отсутствия буферизации.

Если вы запускаете это в Windows, вы можете получить немного, написав свой собственный буфер потока и напрямую связав CreateFile, передав (например) FILE_FLAG_SEQUENTIAL_SCAN или FILE_FLAG_NO_BUFFERING. В этих обстоятельствах любой из них может существенно помочь вашей работе.

Ответ 3

Если вам нужна реальная скорость, вам придется прекратить чтение строк в std::string и начать использовать char* в буфере. Если вы читаете этот буфер, используя ifstream::read() или файлы с отображением памяти, менее важны, хотя у read() есть недостаток, который вы замечаете о потенциально имеющем N полных строках и неполном в буфере и нуждающемся в его распознавании (может легко это сделать путем сканирования остальной части буфера для '\n' - возможно, поместив NUL после буфера и используя strchr). Вам также потребуется скопировать частичную строку в начало буфера, прочитать следующий фрагмент из файла, чтобы он продолжался с этой точки, и изменить максимальное количество символов, прочитанных так, чтобы он не переполнял буфер. Если вы нервничаете о FILE *, я надеюсь, что вам будет удобно со const char *....

Как вы предлагаете это по соображениям производительности, я надеюсь, что вы профилировали, чтобы убедиться, что это не ваше извлечение полей в CSV и т.д., это реальное узкое место.

Ответ 4

Надеюсь, это поможет -

http://www.cppprog.com/boost_doc/doc/html/interprocess/sharedmemorybetweenprocesses.html#interprocess.sharedmemorybetweenprocesses.mapped_file

Кстати, вы написали "Я вижу много проблем с решением, например, буфер может иметь неполные строки и т.д." - в этой ситуации, как читать 250 МБ, а затем читать char на char, пока вы не получите разделитель завершите линию.