明らかな違いは、 API をGetFileSize2
使用してファイル ハンドルを取得してファイルを開くことです。CreateFile
対照的にGetFileSize1
、ファイルのメタデータからサイズを読み取るため、そうではありません。
GetFileSize1
ですから、より良いパフォーマンスを期待したいと思います。ただし、多くのアプリケーションでは、パフォーマンスの違いは問題になりません。さらに重要なことに、成功するGetFileSize2
状況でも共有違反が原因で失敗する可能性があります。GetFileSize1
したがって、実際には使用しないでくださいGetFileSize2
。
また、提示した 2 つの関数は、エラーが発生した場合の動作が異なることに注意してください。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;
または、エラーの場合に -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;
を呼び出すよりも自然に感じる方法もあります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;
更新: @CodeInChaos は、ファイル ハンドルを開かないアプローチについて適切に指摘しています。これらのアプローチは、ハード リンクされたファイルに対して不正確な結果をもたらす可能性があります。