Delphi 6 支持大文件吗? (替换系统模块?)

发布于 2024-11-07 19:06:36 字数 447 浏览 4 评论 0原文

我在与巨大的固定长度记录数据文件交互时遇到问题。该文件大小超过 14 GB。当我看到 System.Filesize() 函数的返回值远小于大文件中的实际记录数(考虑到文件中的字节数和每条记录的长度。 (System.Filesize 返回非类型化文件中给定 Reset() 调用期间指定的记录大小的记录数。它不返回文件中的字节数)。我将其归因于 System.Filesize() 的返回类型是 Longint 而不是 Int64。

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

Delphi 6 是否有一个替代模块可以处理大文件并且可以替代系统单元文件 I/O 调用?如果可以的话,我会尽量避免自己动手。

I am running into problems interacting with a huge fixed length record data file. The file is over 14 GB in size. I first noticed a problem when I saw the return value from the System.Filesize() function was far less than the actual number of records in the huge file, given the number of bytes in the file and the length of each record. (System.Filesize returns the number of records in an untyped file given the record size specified during the Reset() call. It does not return the number of bytes in the file). I chalked it up to the return type of System.Filesize() being a Longint instead of an Int64.

I worked around the initial problem by calling GetFileSizeEx() and calculating the number of records myself. Unfortunately, BlockRead() also fails when trying to access records in the file whose offset is deep into the file. I'm guessing that again there are values being used that are overflowing somewhere in the code.

Is there a replacement module out for Delphi 6 there that can handle huge files and is a substitute for the System unit file I/O calls? I'm trying to avoid rolling my own if I can.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

寄离 2024-11-14 19:06:36

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

You can use the GpHugeFile from Primoz Gabrijelcic. I used this library myself to access larger files (> 2gb) from Delphi 7. Anyway in your case you must consider try to change you app logic and migrate to a Database scheme which is much more efficient which a scheme based in record files.

遗弃M 2024-11-14 19:06:36

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

It turns out that the internal seek routine used by the System unit also had problems due to the use of low capacity numeric types. I coded up my own call to the Windows SetFilePointerEx() function and all is well. I have provided the source code below in case it might help others. I have included the code I created to get the number of records properly too since you will need both. Everything else works the same.

// 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;
无可置疑 2024-11-14 19:06:36

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

You can't use Pascal I/O with huge files like this, not in any version of Delphi. Your best bet is to use a TFileStream which has no such limitations.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文