Mega Code Archive

 
Categories / Delphi / Files
 

How to get a file size algorithmic way

Title: How to get a file size algorithmic way Question: In article http://www.delphi3000.com/articles/article_2351.asp by Adam Lanzafame shows how to use windows api to format a file size using api in this article I show how to do it using algorithm Answer: In the article mentioned above you get a way to format a filesize by using windows api, however these haves its drawbacks, just to name the most interesting, take a look at how rounding works that way if a file is 14.569 KB windows will round it to 14.56 KB instead of 14.57 KB, why? I dont know it and this article seeks not to discuss it however here is a function wich does the same formatting while avoiding the mentioned rounding problem: function GetAFileSize(SizeInBytes: Integer): String; const Preffixes: array[0..3] of String = //Common file sizes preffixes (' Bytes', ' KB', 'MB', ' GB'); //Change if you want to anything that suits FormatSpecifier: array[Boolean] of String = ('%n', '%.2n'); //the way we format the string; var i: integer; //A counter TmpSize: Real; //A temporary variable begin i := -1; //Avoid compiler complain tmpSize := SizeInBytes; //Avoid compiler complain while (i // a file will rarely pass a GB up to 3 begin TmpSize := TmpSize / 1024; //1 MB = 1024 KB, 1 KB = 1024 Bytes, 1 Byte = 8 Bits, 1 bit = nothing inc( i ); //increment counter and select preffix string if Trunc( TmpSize )= 0 then //we reached a maximum nuber of divisions so begin TmpSize := TmpSize * 1024; //Tmpsize was divided 1 time more than necessary Break; //Exit of loop; end; end; //Actual formatting routine Result := Format(FormatSpecifier[((Frac(TmpSize)*10) 1)], [TmpSize]) + Preffixes[i]; end; Notes of interest: * These algorithm relies on delphi native format function, wich kind of limits it * It isnot part of windows api, you have to copy and paste it whenever you use it * Unlike windows api it has correct rounding and can be extended This compact function with a couple of changes could be used as a export function in a dll, as a matter of fact here is some code wich "serves this purpose" function MYStrFormatByteSizeA(dwSize: Integer; pszBuf: PChar; cchBuffsize: integer): PChar; const Preffixes: array[0..3] of PChar = (' Bytes', ' KB', 'MB', ' GB'); FormatSpecifier: array[Boolean] of PChar = ('%n', '%.2n'); var i: integer; TmpSize: Real; TmpResult: PChar; begin i := -1; tmpSize := dwSize; while (i begin TmpSize := TmpSize / 1024; inc( i ); if Trunc( TmpSize )= 0 then begin TmpSize := TmpSize * 1024; Break; end; end; // Since working with PChars here have to think PChar StrFmt( TmpResult, FormatSpecifier[((Frac(TmpSize)*10) 1)], [TmpSize] ); StrCat( TmpResult, Preffixes[i] ); Result := TmpResult; end; An example to use any of the functions above: function getfilesizeex(AFilename: string): String; //must include complete filepath var ASR: TSearchRec; Size: Integer; begin FindFirst(AFileName, faArchive, ASR); Size := ASR.FindData.nFilesizeHigh * MaxDWord + ASR.FindData.nFileSizeLow Result := GetAFileSize( Size ); FindClose( ASR ); end; Truly yours The Object Pascal guy