Get file sizes> And then Get total size?

It should be easy, but I can’t get it right, because I seem to be confusing myself and converting to and from strings, integers and floats and much more.

Basically, I populate a TListView with the names FileNames in one column, and in the other column it returns the file size to the corresponding file_name. I use a pretty neat feature from here that 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 can be populated like this:

enter image description here

Now, in the size of the label data, I would like to return the total size of the files in the Listview, so in this example, the values ​​from the Size column will need to be added to return the total size, for example:

1.28 MB + 313.90 KB + 541.62 KB + 270.96 KB

Obviously, it cannot be added in the same way, because the values ​​contain decimal points, some values ​​can be in Kb, others in Mb, etc. This is my problem, I can’t come up with a simple solution to add (receive) the total file size, and then return it to the same formatted string as shown.

I would really like understanding or advice on how to work with such data, I just endlessly confuse myself with different transformations, etc., and don’t know which way to do it.

Thank you very much in advance:)

UPDATE 1

Following Marc B's recommendations, 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 can be useful for someone else if they need it :)

UPDATE 2

Also, see Ken White's answer for more valuable information and a cleaner update to the GetSizeOfFile function, which works just fine:

enter image description here

+4
source share
2 answers

Separate "get file information" from "format the size string" to two separate functions. The file information function extracts the file size and adds it to the total, THEN calls the format function to convert a simple integer to the string "nice".

+6
source

The easiest way is to change your function to return the file size, and use a separate function to format the results.

I know that you already accepted the answer, but the updated code that you posted has several problems (one was also in the original version).

Firstly, your way to get the file size is very slow, especially if you are going to use it to display a large number of files. In fact, you open the file by moving the file pointer to the end of the file to get the size, and then close the file. In addition, this may fail if the file is open only for another application.

Secondly, your new version of GetSizeOfFile has a logical error. Each time you add to the global cumulative value (this is what you want), but you also return this new global value that you do not want according to the posted pattern.

This replaces GetSizeOfFile , which should work for you, as well as a usage example:

 function GetSizeOfFile( const FileName: String ): Int64; var Rec : TSearchRec; begin Result := 0; if (FindFirst(FileName, faAnyFile, Rec) = 0) then begin Result := Rec.Size; FindClose(Rec); end; end; 

Using an example:

 var FileSize: Int64; FileSizeString: string; begin { Whatever code } FileSize := GetSizeOfFile(SomeFileName); iFileSize := iFileSize + NewSize; FileSizeString := FormatFileSize(NewSize); { Add your file to your ListView.} end; 
+2
source

Source: https://habr.com/ru/post/1383215/


All Articles