Search code examples
delphidelphi-7

Delphi file size back to an Int64?


I have some large files I need to process and would like to indicate to the user the file size as the processing may take a long time.

I am using David Heffernan's function (a BIG thanks there David) to get the size and it works just great.

function GetFileSize3(const FileName: string): Int64;
var
  fad: TWin32FileAttributeData;
begin
  if not GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @fad) then
    RaiseLastOSError;
  Int64Rec(Result).Lo := fad.nFileSizeLow;
  Int64Rec(Result).Hi := fad.nFileSizeHigh;
end;

I then convert that to a string and store it and others in a StringList for later use.

When I try to convert it back to an Int64 value (myInt64:=StrToInt(slSize[j])) I get an error, "xxx is not an Integer" or something very close to that error.

I guess I should have used an Array of Record with Filename:String; Size:Int64; etc in the Record instead of using StringLists. Hindsight is wonderful, and it would now take a major re-write to use an Array of Records at this point.

I need a cheater's way to convert the very large StringList values back to an Int64 for the few files that are going to be outside the normal StrToInt( function that causes the error.

Anyone care to save my bacon? Thank you.


Solution

  • Use StrToInt64 instead. (The link is to the current documentation, but the function exists in Delphi 7 as well, in the SysUtils unit.)

    myInt64 := StrToInt64(slSize[j]);
    

    Better yet, don't store it in a string in the first place. Store it in an Int64, and only convert it to a string when you need it in one (such as for displaying in a label). If you plan on using it as a number, store it as a number.

    You can always create a small class that just contains an Int64, and store that in the TStringList.Objects along with the string that has the file name, and read it back from the Objects when you need the size. You could even add a property to that small class that handles the conversion to a string for when you need it.

    type
      TFileSizeInfo = class(TObject)
      private
        FFileSize: Int64;
        function GetFileSizeAsString: string;
      public
        constructor Create(TheFileSize: Int64);
        property AsInt64: Int64 read FFileSize write FFileSize;
        property AsString: string read GetFileSizeAsString;
      end;
    
    implementation
    
    constructor TFileSizeInfo.Create(TheFileSize: Int64);
    begin
      inherited Create;
      FFileSize := TheFileSize;
    end;
    
    function TFileSizeInfo.GetFileSizeAsString: string;
    begin
      Result := IntToStr(FFileSize);
    end;
    

    Using it:

    // Add to stringlist
    var
      FileSizeInfo: TFileSizeInfo;
    begin
      FileSizeInfo := TFileSizeInfo.Create(GetFileSize3(TheFleName);
      slSize.AddObject(TheFileName, FileSizeInfo);
    end;
    
    // Reading it back
    var
      SizeAsInt64: Int64;
      SizeAsString: string;
    begin
      SizeAsInt64 := TFileSizeInfo(slSize.Objects[Index]).AsInt64;
      SizeAsString := TFileSizeInfo(slSize.Objects[Index]).AsString;
    end;
    
    // Clearing your `TStringList` and its `Objects`
    procedure ClearFileList(TheList: TStringList);
    var
      i: Integer;
    begin
      for i := 0 to TheList.Count - 1 do
        TheList.Objects[i].Free;
      TheList.Clear;
    end;