Огромная поддержка файлов для Delphi 6?(замена системного модуля?) - PullRequest
3 голосов
/ 19 мая 2011

У меня проблемы с взаимодействием с огромным файлом данных фиксированной длины.Размер файла превышает 14 ГБ.Я впервые заметил проблему, когда увидел, что возвращаемое значение из функции System.Filesize() было намного меньше, чем фактическое количество записей в огромном файле, учитывая количество байтов в файле и длину каждой записи.(System.Filesize возвращает количество записей в нетипизированном файле с учетом размера записи, указанного во время вызова Reset(). Он не возвращает количество байтов в файле).Я записал это в качестве типа возврата System.Filesize(), представляющего собой Longint вместо Int64.

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

Есть ли модуль замены для Delphi 6, который может обрабатывать огромные файлы и является заменой для файла системного блока I/ O звонки?Я стараюсь не кататься, если могу.

Ответы [ 4 ]

6 голосов
/ 19 мая 2011

Вы можете использовать GpHugeFile из Primoz Gabrijelcic .Я сам использовал эту библиотеку для доступа к более крупным файлам (> 2 ГБ) из Delphi 7. В любом случае, вы должны подумать о том, чтобы попытаться изменить логику вашего приложения и перейти на схему базы данных, которая гораздо более эффективна, чем схема, основанная на файлах записей.

2 голосов
/ 19 мая 2011

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

// Some constants
const
    kernel = 'kernel32.dll';


function SetFilePointerEx(hFile: Integer; distanceToMove: Int64; var newFilePointer: Int64; moveMethod: DWORD): boolean; stdcall; external kernel name 'SetFilePointerEx';


// easyGetFileSize() is a replacement filesize function.  Use it to get the number of bytes in the huge file.  To get the number of records just "div" it by the record size.

function GetFileSizeEx(hFile: THandle; var FileSize: Int64): BOOL; stdcall; external 'kernel32.dll' name 'GetFileSizeEx';


function easyGetFileSize(theFileHandle: THandle): Int64;
begin
    if not GetFileSizeEx(theFileHandle, Result) then
        RaiseLastOSError;
end;

// ---- Replacement seek function.  Use this instead.

procedure mySeek(var f: File; recordSize, recNum: Int64);

var
    offsetInBytes, numBytesRead: Int64;
    pBigInt: ^Int64;
begin
    offsetInBytes := recNum * recordSize;

    pBigInt := nil; // Not interested in receiving a new pointer after seek.

    // Call the Windows seek call since Delphi 6 has problems with huge files.
    if not SetFilePointerEx(TFileRec(f).Handle, offsetInBytes, pBigInt^, FILE_BEGIN) then
        raise Exception.Create(
            '(mySeek) Seek to record number # '
            + IntToStr(recNum)
            + ' failed');
end;
2 голосов
/ 19 мая 2011

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

1 голос
/ 19 мая 2011

Нельзя использовать ввод-вывод Pascal с такими большими файлами, как ни в одной версии Delphi. Лучше всего использовать TFileStream, который не имеет таких ограничений.

...