Ответ 1
Попробуйте использовать функцию отображения отображаемой памяти Windows. Вызовы буферизуются, и вы можете обращаться с файлом, как с его простой памятью. отображенные карты памяти
Мне нужно прочитать большой текстовый файл ( > 10 ГБ) на С++. Это файл csv с переменными длинными строками. когда я пытаюсь читать по строкам, используя ifstream, он работает, но занимает много времени, я думаю, это связано с тем, что каждый раз, когда я читаю строку, она переходит на диск и читает, что делает ее очень медленной.
Есть ли способ читать в буферах, например, читать 250 МБ на одном снимке (используя метод чтения ifstream), а затем получать строки из этого буфера, я вижу много проблем с решением, например буфером, может иметь неполные строки и т.д..
Есть ли решение для этого в С++, которое обрабатывает все эти случаи и т.д. Существуют ли библиотеки с открытым исходным кодом, которые могут это сделать, например boost и т.д.
Примечание. Я бы хотел избежать указателей FILE * и т.д.
Попробуйте использовать функцию отображения отображаемой памяти Windows. Вызовы буферизуются, и вы можете обращаться с файлом, как с его простой памятью. отображенные карты памяти
IOstream уже используют буферы так же, как вы описали (хотя обычно это всего несколько килобайт, а не сотни мегабайт). Вы можете использовать pubsetbuf
, чтобы заставить его использовать больший буфер, но я бы не ожидал каких-либо огромных выигрышей. Большая часть накладных расходов в IO-потоках связана с другими областями (например, с использованием виртуальных функций), а не из-за отсутствия буферизации.
Если вы запускаете это в Windows, вы можете получить немного, написав свой собственный буфер потока и напрямую связав CreateFile
, передав (например) FILE_FLAG_SEQUENTIAL_SCAN
или FILE_FLAG_NO_BUFFERING
. В этих обстоятельствах любой из них может существенно помочь вашей работе.
Если вам нужна реальная скорость, вам придется прекратить чтение строк в std::string и начать использовать char*
в буфере. Если вы читаете этот буфер, используя ifstream::read()
или файлы с отображением памяти, менее важны, хотя у read() есть недостаток, который вы замечаете о потенциально имеющем N полных строках и неполном в буфере и нуждающемся в его распознавании (может легко это сделать путем сканирования остальной части буфера для '\n' - возможно, поместив NUL после буфера и используя strchr
). Вам также потребуется скопировать частичную строку в начало буфера, прочитать следующий фрагмент из файла, чтобы он продолжался с этой точки, и изменить максимальное количество символов, прочитанных так, чтобы он не переполнял буфер. Если вы нервничаете о FILE *, я надеюсь, что вам будет удобно со const char *....
Как вы предлагаете это по соображениям производительности, я надеюсь, что вы профилировали, чтобы убедиться, что это не ваше извлечение полей в CSV и т.д., это реальное узкое место.
Надеюсь, это поможет -
Кстати, вы написали "Я вижу много проблем с решением, например, буфер может иметь неполные строки и т.д." - в этой ситуации, как читать 250 МБ, а затем читать char на char, пока вы не получите разделитель завершите линию.