FileSize,与这个程序有什么区别,哪个更好用?

Mar*_*ato 7 delphi delphi-xe2

关于获取文件的大小,我有这两个功能:

function GetFileSize1(const FileName: TFileName): Int64;
var
 iTmp: Int64;
 SearchRec: TSearchRec;
begin
  iTmp := -1;
  if FindFirst(FileName, faAnyFile, SearchRec) = 0 then
  begin
    iTmp := SearchRec.Size;
    System.SysUtils.FindClose(SearchRec);
  end;
  Result := iTmp;
end;
Run Code Online (Sandbox Code Playgroud)

和:

function GetFileSize2(const FileName: TFileName): Int64;
var
 FileStream: TFileStream;
begin
  FileStream := TFileStream.Create(FileName, fmOpenRead);
  try
    Result := FileStream.Size; 
  finally  
    FileStream.Free;
  end; 
end;
Run Code Online (Sandbox Code Playgroud)

在实践中,它有什么区别?当然,两者都返回相同的结果,但更加可信,更快,更安全?或者更好,什么是可取的用途?第一还是第二?非常感谢.

Dav*_*nan 8

好吧,明显的区别是GetFileSize2打开文件,使用CreateFileAPI获取文件句柄.相反,GetFileSize1不是因为它从文件元数据中读取大小.

所以我希望GetFileSize1表现更好.虽然,对于许多应用程序而言,性能差异无关紧要.更重要的是,GetFileSize2由于在GetFileSize1成功的情况下发生共享违规,可能会失败.所以你真的不应该使用GetFileSize2.

另请注意,出现错误时,您呈现的两个函数的行为会有所不同:GetFileSize1返回-1,并GetFileSize2引发异常.

我个人更喜欢这个版本:

function GetFileSize3(const FileName: string): Int64;
var
  fad: TWin32FileAttributeData;
begin
  if not GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @fad) then
    RaiseLastOSError;
  Int64Rec(Result).Lo := fad.nFileSizeLow;
  Int64Rec(Result).Hi := fad.nFileSizeHigh;
end;
Run Code Online (Sandbox Code Playgroud)

或者,如果您希望在出现错误时返回-1,则可以这样写:

function GetFileSize3(const FileName: string): Int64;
var
  fad: TWin32FileAttributeData;
begin
  if not GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @fad) then
    exit(-1);
  Int64Rec(Result).Lo := fad.nFileSizeLow;
  Int64Rec(Result).Hi := fad.nFileSizeHigh;
end;
Run Code Online (Sandbox Code Playgroud)

有些人觉得这比自然更自然FindFirstFile,但这可能仅仅是个人偏好.这种FindFirstFile方法确实没有错.虽然它不需要那个iTmp变量.你可以这样写得更清楚:

function GetFileSize1(const FileName: TFileName): Int64;
var
 SearchRec: TSearchRec;
begin
  if FindFirst(FileName, faAnyFile, SearchRec) = 0 then
  begin
    Result := SearchRec.Size;
    System.SysUtils.FindClose(SearchRec);
  end
  else
    Result := -1;
end;
Run Code Online (Sandbox Code Playgroud)

更新: @CodeInChaos对未打开文件句柄的方法提出了一个很好的观点.这些方法可能会给硬链接文件带来不准确的结果.


Sir*_*ufo 2

不同之处在于,GetFileSize1 读取文件的元信息(Windows-API-Call),而 GetFileSize2 直接接触文件(获取 FileHandle,遍历直到最后计算大小)。

因此 GetFileSize1 比 GetFileSize2 消耗更少的性能/资源

更新

我忘了提及,如果文件已在使用中,您可能不允许使用 TFileStream 进行访问,但元信息将可用。

更新(只是戴维斯建议的另一个变体)

function GetFileSize1(const FileName: TFileName): Int64;
var
 SearchRec: TSearchRec;
begin
  if FindFirst( FileName, faAnyFile, SearchRec ) = 0 then
    try
      Exit( SearchRec.Size );
    finally
      System.SysUtils.FindClose(SearchRec);
    end;
  Result := -1;
end;
Run Code Online (Sandbox Code Playgroud)