2006. július 5., szerda

Determine file and tree sizes larger 2 GB

Problem/Question/Abstract:

How to determine file and tree sizes larger 2 GB

Answer:

Solve 1:

You will need to use the FindFirstFile, FindNextFile and FindClose functions, e.g.:

function GetFileSize(const FileName: string): Int64;
var
F: TWin32FindData;
H: THandle;
begin
H := FindFirstFile(PChar(FileName), F);
if H = INVALID_HANDLE_VALUE then
RaiseLastWin32Error;
try
Result := F.nFileSizeHigh shl 32 + F.nFileSizeLow;
finally
Windows.FindClose(H);
end;
end;

function GetTreeSize(FileName: string): Int64;

procedure TreeSize(const FileName: string);
var
F: TWin32FindData;
H: THandle;
begin
H := FindFirstFile(PChar(FileName), F);
if H = INVALID_HANDLE_VALUE then
RaiseLastWin32Error;
try
repeat
if ((F.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) > 0) and (F.cFileName[0]
<> '.') then
TreeSize(ExtractFilePath(FileName) + F.cFileName + '\*.*')
else
Result := Result + F.nFileSizeHigh shl 32 + F.nFileSizeLow;
until not FindNextFile(H, F);
finally
Windows.FindClose(H);
end;
end;

begin
Result := 0;
TreeSize(IncludeTrailingBackslash(ExtractFilePath(FileName)) + '*.*');
end;

I would add one little detail to your function. By calculating the filesize, you should cast the values to Int64. In the helpfile you can read, that this is necessary, because the operation would normally return an integer. In this case, (F.nFileSizeHigh shl 32) would return an Integer and not an Int64.

Result := Int64(F.nFileSizeHigh) shl 32 + Int64(F.nFileSizeLow);

I think, casting "nFileSizeLow" is not necessary, but better to make it safe.


Solve 2:

Use the WinAPI version of the function GetFileSize() as follows:

procedure CardinalsToI64(var I: Int64; const LowPart, HighPart: Cardinal);
begin
TULargeInteger(I).LowPart := LowPart;
TULargeInteger(I).HighPart := HighPart;
end;

{ ... }
var
fLOdword: dword;
fHIdword: dword;
FFilesize: Int64;
FFileHandle: THandle;
begin
FFileHandle := CreateFile(PChar(FFileName), GENERIC_READ, FILE_SHARE_READ, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
fLOdword := GetFileSize(FFileHandle, @fHIdword);
CardinalsToI64(FFilesize, fLOdword, fHIdword);


Solve 3:

function GetFileSize(const FileName: string): Int64;
var
SizeLow, SizeHigh: DWord;
hFile: THandle;
begin
Result := 0;
hFile := FileOpen(FileName, fmOpenRead);
try
if hFile <> 0 then
begin
SizeLow := Windows.GetFileSize(hFile, @SizeHigh);
Result := (SizeHigh shl 32) + SizeLow;
end;
finally
FileClose(hFile);
end;
end;


Nincsenek megjegyzések:

Megjegyzés küldése