【问题标题】:Speed Issues With FileSize FunctionFileSize 函数的速度问题
【发布时间】:2014-08-04 07:58:40
【问题描述】:

好的,

我使用此函数在我的程序中获取文件大小,即使对于 4GB 以上的文件,它也能正常工作。

function FileSize(const PathtoFile: string): Int64;
var
  AttributeData: TWin32FileAttributeData;
begin
  if GetFileAttributesEx(PChar(PathtoFile), GetFileExInfoStandard,
    @AttributeData) then
  begin
    Int64Rec(Result).Lo := AttributeData.nFileSizeLow;
    Int64Rec(Result).Hi := AttributeData.nFileSizeHigh;
  end
  else
    Result := -1;
end;

现在,问题是当使用 AQTime Standard 分析我的应用程序时,我发现我的程序在获取大约 4758 Files 的文件大小时在此函数中花费了大约 35 Secs,而我在处理时的时间是 GetFileAttribute Function Spends which is about 5 Secs相同数量的文件。 请问有什么代码可以代替我当前的代码(即使它是 ASM)来加快操作速度。

【问题讨论】:

  • 文件都在同一个目录吗?如果是这样,Windows 本身就会在单个目录中出现大量 (4K) 文件的问题。文件是否位于网络驱动器上?您还可能遇到网络延迟问题。我针对 FindFirstFileEx 测试了您的代码,并且返回网络驱动器上单个文件的大小对于这两个函数花费了完全相同的时间(3 毫秒);根据 TStopWatch 计时,使用本地文件进行测试需要 0 毫秒。
  • 目录中的文件大小不一。

标签: delphi


【解决方案1】:

GetFileAttributesEx 和 GetFileAttributes 都是 windows api 调用。那里确实没有太大的收获。

您可以考虑的一件事是直接阅读 MFT,如果您让它工作起来,速度会非常快。不过,这不是一个简单的 5 行解决方案。

有关更多信息,请参阅此答案:https://stackoverflow.com/a/3061745/1107597

【讨论】:

  • 感谢您的建议。会调查的。不过仍在等待其他一些建议:)。
【解决方案2】:

您可以尝试使用 FindFist 获取文件大小,然后从 TSearchRec 读取此函数返回的 Size 字段。

【讨论】:

  • 感谢您的建议,但我希望远离 FindFirst Stuff。
  • @Xor-el,你有没有试过用“FindFirst Stuff”和GetFileAttributesEx比较速度
  • @kobik,我会这样做,但我目前不在我的开发 PC 上。
  • @Xor 你想让你的程序运行得更快吗?试试 FindFirstFile 看看是否更快。
  • 我会在我的开发 PC 上执行此操作。谢谢。
【解决方案3】:

你可以试试这个:

function getFileSize( vFileName : String ) : Int64;
var F : TFileStream;
begin
  Result := 0; // or -1

  try

    if FileExists( vFileName ) then
    try
      F := TFileStream.Create( vFileName );
      Result := F.Size;
    finally
      F.Free;
    end;

  except end;

end;

或者像KobikDavid说的:

function getFileSizeInteger( vFileName : String ) : Integer;
var SR : TSearchRec;
begin
  Result := 0; // or -1

  if FindFirst( vFileName, faArchive, SR ) then
  try
    Result := SR.Size;
  finally
    FindClose( SR );
  end;

end;

第二个选项(使用 FindFirst)的问题是 Result 仅限于整数范围 (4GB)。

第一个选项对我来说在各个方面都足够好。

【讨论】:

  • 感谢您的建议,但第一个函数必须创建一个流,这会产生一些开销,这比我的第一个函数要高得多。将尝试 kobik 和 david 方法并报告。
  • -1。第一个选项根本不可接受。它不仅需要打开文件并执行 Seek 来查找大小,而且如果无法打开文件,它会失败,并且可能导致其他代码/应用程序失败,因为它会干扰它们打开文件的能力. FindFirst 不是替代方案,因为发帖人曾提到文件有时会大于 4GB。 IOW,您提出的解决方案都不是该问题的可行答案。
  • 为什么不能返回 Int64?
  • Ken White:我只是想帮忙......我说第二个选项有大小问题,只是弄清楚上面的 cmets。我用第一个选项在短短 10 秒内检查了大约 5k 个文件的大小……这还不算太糟糕以至于失去了我的声誉。让用户接受或不接受答案!
  • @SertacAkyuz:即使在使用整数表示TSearchRec.Size 的旧版本中,您也可以通过使用TSearchRec.FindData.nFileSize(Low/High) 而不是TSearchRec.Size 来获得完整的Int64 值。
猜你喜欢
  • 2010-11-20
  • 1970-01-01
  • 1970-01-01
  • 2011-05-15
  • 2011-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多