对Delphi 6的大量文件支持? (更换系统模块?)

时间:2011-05-18 21:41:35

标签: delphi int64 large-data

我遇到了与巨大的固定长度记录数据文件交互的问题。该文件大小超过14 GB。我首先注意到一个问题,当我看到System.Filesize()函数的返回值远远小于大文件中的实际记录数时,给定文件中的字节数和每个记录的长度。 (给定在Reset()调用期间指定的记录大小,System.Filesize返回无类型文件中的记录数。它不返回文件中的字节数)。我将它归结为返回类型System.Filesize()是Longint而不是Int64。

我通过调用GetFileSizeEx()并自己计算记录数来解决最初的问题。不幸的是,BlockRead()在尝试访问文件中偏移深入文件的记录时也会失败。我猜再次使用的值正在代码中的某处溢出。

Delphi 6是否有可以处理大文件的替换模块,可替代系统单元文件I / O调用?如果可以的话,我试图避免自己动手。

4 个答案:

答案 0 :(得分:6)

您可以使用GpHugeFile中的Primoz Gabrijelcic。我自己使用这个库从Delphi 7访问更大的文件(> 2gb)。无论如何,在你的情况下,你必须考虑尝试改变你的app逻辑并迁移到数据库方案,这对于基于记录文件的方案来说效率要高得多。

答案 1 :(得分:2)

尝试TGpHugeFile

答案 2 :(得分:2)

事实证明,由于使用低容量数字类型,系统单元使用的内部搜索例程也存在问题。我编写了自己对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;

答案 3 :(得分:1)

你不能在这样的大文件中使用Pascal I / O,不能在任何版本的Delphi中使用。您最好的选择是使用没有此类限制的TFileStream