Огромная поддержка файлов для Delphi 6? (замена системного модуля?)
У меня проблемы с взаимодействием с огромным файлом данных фиксированной длины. Размер файла превышает 14 ГБ. Я впервые заметил проблему, когда увидел возвращаемое значение из System.Filesize()
Функция была намного меньше, чем фактическое количество записей в огромном файле, учитывая количество байтов в файле и длину каждой записи. (System.Filesize возвращает количество записей в нетипизированном файле, учитывая размер записи, указанный во время Reset()
вызов. Это не возвращает количество байтов в файле). Я записал это на счет типа возврата System.Filesize()
будучи Longint вместо Int64.
Я обошел начальную проблему, позвонив GetFileSizeEx()
и вычисление количества записей самостоятельно. К несчастью, BlockRead()
также происходит сбой при попытке доступа к записям в файле, смещение которых находится глубоко в файле. Я предполагаю, что снова есть значения, которые используются где-то в коде.
Существует ли модуль замены для Delphi 6, который может обрабатывать огромные файлы и является заменой для вызовов ввода-вывода файлов системного блока? Я стараюсь не кататься, если могу.
4 ответа
Вы можете использовать GpHugeFile
от gabr. Я сам использовал эту библиотеку для доступа к большим файлам (> 2 ГБ) из Delphi 7. В любом случае, в вашем случае вы должны попытаться изменить логику вашего приложения и перейти на схему базы данных, которая гораздо более эффективна, чем схема, основанная на файлах записей.
Оказывается, что внутренняя процедура поиска, используемая системным блоком, также имела проблемы из-за использования числовых типов малой емкости. Я кодировал свой собственный вызов функции 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;
Вы не можете использовать ввод / вывод Pascal с такими огромными файлами, как ни в одной версии Delphi. Лучше всего использовать TFileStream
который не имеет таких ограничений.