Искать текстовый файл - PullRequest
       0

Искать текстовый файл

6 голосов
/ 17 января 2011

Я работаю с очень большими текстовыми файлами, 2 ГБ и более.Я хотел бы иметь функцию, похожую на Seek ().Кто-нибудь делал что-то подобное?Загрузка в TStringList исключена.Также работает с нетипизированным файлом.Сейчас я использую readLn, но это длится слишком долго.Спасибо.

Ответы [ 5 ]

13 голосов
/ 18 января 2011

Отображение файла в память (CreateFileMapping / MapViewOfFile) по частям, затем сканирование отображенной памяти и построение индекса - списка позиций начала каждой строки.Тогда ваша операция поиска будет выполнена путем получения позиции N-й строки в файле и поиска этой позиции.Затем используйте TFileStream для выполнения произвольного доступа к файлу или, если вы только читаете файл, вы также можете использовать сопоставления файлов для произвольного доступа - это может быть даже быстрее, чем использование TFileStream параллельно с сопоставлением файлов.

3 голосов
/ 18 января 2011

Попробуйте GpHugeFile .

Инкапсуляция процедур обработки файлов Windows, которая позволяет работать с файлами> 2 ГБ.

Включена поддержка небуферизованного доступа (FILE_FLAG_NO_BUFFERING) и буферизация для файлов с последовательным доступом. Включает также класс обертки потока.

2 голосов
/ 18 января 2011

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

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

Как подсказывают другие, базовый механизм должен быть CreateFileMapping / CreateViewOfFile (или mmap в POSIX.)

2 голосов
/ 18 января 2011

Вы установили довольно жесткие граничные условия.

Единственное, что я могу себе представить, это попытаться получить дескриптор из текстового файла и использовать функции win32 для прямого поиска. Остерегайтесь кеширования текстового файла, хотя.

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

Free Pascal имеет функцию getfilehandle для этой цели, чтобы извлечь дескриптор ОС из файлов textfile / tfilerec. Я не знаю, что недавно добавили Delphi в этот отдел.

1 голос
/ 18 января 2011

Вы можете использовать эту функцию для изменения текущей позиции в файле TText:

function TextSeek(var f: Text; position: Int64): boolean;
var pos64: Int64Rec absolute position;
    resHi: cardinal;
begin
  result := false;
  with TTextRec(f) do
  begin
    if mode<>fmInput then
      exit;
    resHi := pos64.Hi;
    if (SetFilePointer(handle,pos64.Lo,@resHi,FILE_BEGIN)<>pos64.Lo) or
       (resHi<>pos64.Hi) then
      exit;
    BufEnd := 0; // flush internal reading buffer
    BufPos := 0;
    result := true; // success
  end;
end;

В случае успеха будет возвращено значение true, при ошибке - значение false (неверная позиция файла не открыта).

Если вы хотите иметь быстрый доступ, убедитесь, что вы установили {$ I-} и проверили IOResult вручную, и вызвали System.SetTextBuffer () с некоторым буфером (от 1 до 64 КБ может иметь смысл).

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