Delphi Format Strings - limits for width and precision values?
Asked Answered
Y

1

5

This statement (in Delphi 7)

writeln(logfile,format('%16.16d ',[FileInfo.size])+full_name);

results in this output

0000000021239384 C:\DATA\DELPHI\sxf_archive10-13.zip

This statement

writeln(logfile,format('%17.17d ',[FileInfo.size])+full_name);

results in this output

         21239384 C:\DATA\DELPHI\sxf_archive10-13.zip

The padding with leading zeros changes to leading spaces when the precision specifier is larger than 16. The help says "If the format string contains a precision specifier, it indicates that the resulting string must contain at least the specified number of digits; if the value has less digits, the resulting string is left-padded with zeros."

Is there another way to format a 20 character integer with leading zeros?

Ylla answered 22/10, 2016 at 22:47 Comment(0)
C
8

Precision of an Integer value is limited to 16 digits max. If the specified Precision is larger than 16, 0 is used instead. This is not a bug, it is hard-coded logic, and is not documented.

There are two ways you can handle this:

  1. use an Int64 instead of an Integer. Precision for an Int64 is 32 digits max:

    WriteLn(logfile, Format('%20.20d %s', [Int64(FileInfo.Size), full_name]);
    

    Note: In Delphi 2006 and later, TSearchRec.Size is an Int64. In earlier versions, it is an Integer instead, and thus limited to 2GB. If you need to handle file sizes > 2GB in earlier versions, you can get the full 64-bit size from the TSearchRec.FindData field:

    var
      FileSize: ULARGE_INTEGER;
    begin
      FileSize.LowPart := FileInfo.FindData.nFileSizeLow;
      FileSize.HighPart := FileInfo.FindData.nFileSizeHigh:
      WriteLn(logfile, Format('%20.20d %s', [FileSize.QuadPart, full_name]);
    end;
    
  2. convert the Integer to a string without any leading zeros, and then use StringOfChar() to prepend any required zeros:

    s := IntToStr(FileInfo.Size);
    if Length(s) < 20 then
      s := StringOfChar('0', 20-Length(s)) + s;
    WriteLn(logfile, s + ' ' + full_name);
    
Cahill answered 23/10, 2016 at 0:24 Comment(1)
Thanks! That is the right way to do this - if I hadn't made the size 64 bit, it would have eventually failed on a >2GB file. When I added the "windows" unit to the uses list for the ULARGE_INTEGER type, it caused an error elsewhere on "Findclose". I had to track down that the Windows unit defines a different findclose procedure, so I had to change my usage to Sysutils.findclose.Ylla

© 2022 - 2024 — McMap. All rights reserved.