Как читать частичные данные из большого текстового файла в C ++ - PullRequest
2 голосов
/ 10 августа 2009

У меня большой текстовый файл, содержащий более 200 000 строк, и мне нужно прочитать всего несколько строк. Например: строка от 10.000 до 20.000.

Важно: я не хочу открывать и искать в полном файле для извлечения строк тезисов из-за проблем с производительностью.

Возможно ли это?

Ответы [ 5 ]

6 голосов
/ 10 августа 2009

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

1 голос
/ 10 августа 2009

Вам придется искать по файлу для подсчета новых строк, если только вы не знаете, что все строки имеют одинаковую длину (в этом случае вы можете искать смещение = line_number * line_size_in_bytes, где line_number отсчитывает от нуля, а line_size_in_bytes включает в себя все символы в строке).

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

0 голосов
/ 10 августа 2009

Как уже отмечали другие, если у вас нет линий фиксированной ширины, невозможно обойтись без построения индекса. Однако, если вы контролируете формат файла, вы можете получить производительность ~ O (log (размер)) вместо O (размер) при поиске начальной строки, если вам удастся сохранить номер самой строки на каждая строка, т.е. чтобы содержимое файла выглядело примерно так:

1: val1, val2, val3
2: val4
3: val5, val6
4: val7, val8, val9, val10

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

Вы должны быть осторожны с угловыми случаями (например, ваше «начало» диапазона и «конец» диапазона находятся на одной линии и т. Д.), Но для меня этот подход отлично работал в Прошло время разбора лог-файлов, в которых была дата (и мне нужно было найти строки между определенными временными метками).

Конечно, это все еще не превосходит производительность явно построенного индекса или записей фиксированного размера.

0 голосов
/ 10 августа 2009

Если линия имеет фиксированную длину, то вы просто вычисляете смещение, без проблем.

Если это не так (то есть обычный файл CSV), то вам нужно будет просмотреть этот файл, либо для создания индекса, либо просто для чтения нужных вам строк. Чтобы сделать чтение файлов немного быстрее, хорошей идеей было бы использовать отображенные в память файлы (см. Реализацию, которая является частью Boost iostreams: http://www.boost.org/doc/libs/1_39_0/libs/iostreams/doc/classes/mapped_file.html).

0 голосов
/ 10 августа 2009

Если эти строки имеют одинаковую длину, вы можете вычислить смещение для данной строки и прочитать только эти байты.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...