This should be easy, but I cannot seem to get it right as I seem to be confusing myself and converting to and from strings, integers and floats and whatnot.
Basically, I am populating a TListView with FileNames in one column, and in another column returning the File Size to the corresponding FileName. I am using a rather neat function found from here, which looks like this:
function FileSizeStr ( filename: string ): string;
const
// K = Int64(1000); // Comment out this line OR
K = Int64(1024); // Comment out this line
M = K * K;
G = K * M;
T = K * G;
var
size: Int64;
handle: integer;
begin
handle := FileOpen(filename, fmOpenRead);
if handle = -1 then
result := 'Unable to open file ' + filename
else try
size := FileSeek ( handle, Int64(0), 2 );
if size < K then result := Format ( '%d bytes', [size] )
else if size < M then result := Format ( '%f KB', [size / K] )
else if size < G then result := Format ( '%f MB', [size / M] )
else if size < T then result := Format ( '%f GB', [size / G] )
else result := Format ( '%f TB', [size / T] );
finally
FileClose ( handle );
end;
end;
This returns values such as: 235.40 KB
So with the above, my TListView may be populated like so:
Now in the Label Data Size, I would like to return the Total Size of the Files in the Listview, so in this example, the values from the Size column would need adding up to return the Total Size, something like:
1.28 MB + 313.90 KB + 541.62 KB + 270.96 KB
Obviously it cannot be added on just like that, because the values contain decimal points, some values may be in Kb, and other in Mb etc. This is my problem, I cannot think of an easy solution to add (get) the Total Size of the Files, and then return it in the same formatted string as shown.
I would really appreciate some insight or tips how to work with this kind of data, I am just endlessly confusing myself with different conversions etc and not really sure which way to do this.
Many Thanks in advance :)
UPDATE 1
Following the advice from Marc B, I changed the function to the following which seems to work:
var
iFileSize: Int64;
implementation
function GetSizeOfFile(FileName: string): Int64;
var
Handle: Integer;
begin
Handle := FileOpen(FileName, fmOpenRead);
if Handle = -1 then
MessageDlg('Unable to open file ' + FileName, mtError, [mbOk], 0)
else try
iFileSize := iFileSize + FileSeek(Handle, Int64(0), 2);
finally
FileClose(Handle);
end;
Result := iFileSize;
end;
function FormatFileSize(AValue: Int64): string;
const
K = Int64(1024);
M = K * K;
G = K * M;
T = K * G;
begin
if AValue < K then Result := Format ( '%d bytes', [AValue] )
else if AValue < M then Result := Format ( '%f KB', [AValue / K] )
else if AValue < G then Result := Format ( '%f MB', [AValue / M] )
else if AValue < T then Result := Format ( '%f GB', [AValue / G] )
else Result := Format ( '%f TB', [AValue / T] );
end;
It may be useful for anyone else should they need it :)
UPDATE 2
Additionally, see the answer Ken White posted which provides more valuable information, and a cleaner update of the GetSizeOfFile function, which works great:
Separate the "get file information" from the "format the size string" into two separate functions. The file information function fetches the file size and adds it to a running total, THEN calls the formatting function to convert the simple integer into the "nice" string.