FileSize, what difference from this procedure and what is better use?

delphi, delphi-xe2

Solution

Well, the obvious difference is that `GetFileSize2` opens the file, using the `CreateFile` API to obtain a file handle. In contrast, `GetFileSize1` does not because it reads the size from the file meta data.

So I would expect `GetFileSize1` to perform better. Although, for many applications that performance difference would not matter. Much more significantly, `GetFileSize2` can fail due to a sharing violation in situations that `GetFileSize1` will succeed. So you really should not use `GetFileSize2`.

Note also that the two functions you present behave differently in case of an error: `GetFileSize1` returns -1, and `GetFileSize2` raises an exception.

Personally I prefer this version:

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;

Or, if you prefer to return -1 in case of error you would write it like this:

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;

Some how this feels more natural than calling `FindFirstFile`, but that's perhaps just personal preference. There's really nothing wrong with the `FindFirstFile` approach. Although it doesn't need that `iTmp` variable. You can write it more clearly like this:

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;

Update: @CodeInChaos makes a good point about the approaches that don't open a file handle. These approaches can give inaccurate results for hard linked files.

Problem

about get size of a file, i have this two functions: ``` 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; ``` And: ``` function GetFileSize2(const FileName: TFileName): Int64; var FileStream: TFileStream; begin FileStream := TFileStream.Create(FileName, fmOpenRead); try Result := FileStream.Size; finally FileStream.Free; end; end; ``` In practise, what is the difference of it? Both return same result of course but what is more affidable, more fast, more secure? Or better, what is preferible use? First or second? Thanks very much.

Original source

Related problems