Title: Get file size as a string revisited - supports huge files
Question: Original articles
Adam Lanzafame demonstrated Win API approach:
http://www.delphi3000.com/articles/article_2351.asp
NYB NYB demonstrated Pascal approach:
http://www.delphi3000.com/articles/article_2357.asp
This article shows a Pascal approach with similar benefits to NYB's code, but supports huge files (files greater than 2 gigabytes) and simplified algorithm (IMHO).
Answer:
Here are a couple of easy to use functions for getting the file size and converting it to an abbreviated notation similar to Explorer.
function GetHugeFileSize(const FileName: string): int64;
The GetHugeFileSize function takes a Filename parameter and returns the file size as an Int64. It will give accurate results for file sizes greater than 2 GB.
function BytesToAbbr(const NumBytes: Int64;
const Format: string = '0.##'): string;
The BytesToAbbr function takes a NumBytes parameter (Int64) and an optional Format parameter (string), and returns a string with the abbreviated byte size. The abbreviation is automatically chosen based on the NumBytes value:
0 - 1023: covert to bytes
1024 - 1048575: covert to KB
1048576 - 1073741823: convert to MB
etc.
The format parameter is used to determine how many decimal places of precision are desired on the output, the default is 2 places ('0.##')
Examples:
BytesToAbbr(25197628224)
BytesToAbbr(25197628224, '0.#')
BytesToAbbr(25197628224, '0.###')
BytesToAbbr(25197628224, '0.####')
returns string results as follows:
23.47 GB
23.5 GB
23.467 GB
23.4671 GB
Using these functions together takes this form:
procedure TForm1.Button1Click(Sender: TObject);
begin
if OpenDialog1.Execute then begin
Label1.Caption := BytesToAbbr(GetHugeFileSize(OpenDialog1.FileName));
end;
end;
Here are the functions:
function BytesToAbbr(const NumBytes: Int64;
const Format: string = '0.##'): string;
const
KiloByte = Int64(1024);
MegaByte = KiloByte * 1024;
GigaByte = MegaByte * 1024;
TeraByte = GigaByte * 1024;
var
Value: Double;
Suffix: string;
begin
Value := 0.0; //This gets rid of compiler warning
//We need this check first since Case doesn't work with
//integer values 32 bits (as of D5);
if NumBytes = GigaByte then begin
if NumBytes Suffix := ' GB';
Value := NumBytes / GigaByte;
end
else begin
Suffix := ' TB';
Value := NumBytes / TeraByte;
end;
end
else //NumBytes is less than 1 GB
case NumBytes of
0..KiloByte-1: begin
Suffix := ' bytes';
Value := NumBytes
end;
KiloByte..MegaByte-1: begin
Suffix := ' KB';
Value := NumBytes / KiloByte;
end;
MegaByte..GigaByte-1: begin
Suffix := ' MB';
Value := NumBytes / MegaByte;
end;
end;
Result := FormatFloat(Format, Value) + Suffix;
end;
function GetHugeFileSize(const FileName: string): int64;
var
FileHandle: hFile;
begin
FileHandle := FileOpen(FileName, fmOpenRead or fmShareDenyNone);
try
LARGE_INTEGER(Result).LowPart := GetFileSize
(FileHandle, @LARGE_INTEGER(Result).HighPart);
if LARGE_INTEGER(Result).LowPart = $FFFFFFFF then
Win32Check(GetLastError = NO_ERROR);
finally
FileClose(FileHandle);
end;
end;
Regards,
Wayne Sherman