Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting size of a file in Delphi 2010 or later?

Delphi 2010 has a nice set of new file access functions in IOUtils.pas (I especially like the UTC versions of the date-related functions). What I miss so far is something like

TFile.GetSize (const Path : String)

What is the Delphi 2010-way to get the size of a file? Do I have to go back and use FindFirst to access TSearchRec.FindData?

Thanks.

like image 203
jpfollenius Avatar asked Oct 29 '09 08:10

jpfollenius


People also ask

How do I find the size of a file in Delphi?

In Delphi code, call FileSize to determine the size of the file specified by the file variable F. The size is expressed as the number of records in a record file. Thus: If the file is declared as a file of byte, then the record size defaults to one byte, and FileSize returns the number of bytes in the file.

How do I know how big my file is?

Locate the file or folder whose size you would like to view. Click the file or folder. Press Command + I on your keyboard. A window opens and shows the size of the file or folder.

Which function is used to get the size of a file?

Explanation: The function filesize() returns the size of the specified file and it returns the file size in bytes on success or FALSE on failure.


4 Answers

I'm not sure if there's a "Delphi 2010" way, but there is a Windows way that doesn't involve FindFirst and all that jazz.

I threw together this Delphi conversion of that routine (and in the process modified it to handle > 4GB size files, should you need that).

  uses     WinApi.Windows;    function FileSize(const aFilename: String): Int64;   var     info: TWin32FileAttributeData;   begin     result := -1;      if NOT GetFileAttributesEx(PWideChar(aFileName), GetFileExInfoStandard, @info) then       EXIT;      result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);   end; 

You could actually just use GetFileSize() but this requires a file HANDLE, not just a file name, and similar to the GetCompressedFileSize() suggestion, this requires two variables to call. Both GetFileSize() and GetCompressedFileSize() overload their return value, so testing for success and ensuring a valid result is just that little bit more awkward.

GetFileSizeEx() avoids the nitty gritty of handling > 4GB file sizes and detecting valid results, but also requires a file HANDLE, rather than a name, and (as of Delphi 2009 at least, I haven't checked 2010) isn't declared for you in the VCL anywhere, you would have to provide your own import declaration.

like image 53
Deltics Avatar answered Sep 20 '22 08:09

Deltics


Using an Indy unit:

uses IdGlobalProtocols;  function FileSizeByName(const AFilename: TIdFileName): Int64; 
like image 40
tz. Avatar answered Sep 19 '22 08:09

tz.


You can also use DSiFileSize from DSiWin32. Works in "all" Delphis. Internally it calls CreateFile and GetFileSize.

function DSiFileSize(const fileName: string): int64;
  var
    fHandle: DWORD;
  begin
    fHandle := CreateFile(PChar(fileName), 0, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if fHandle = INVALID_HANDLE_VALUE then
      Result := -1
    else try
      Int64Rec(Result).Lo := GetFileSize(fHandle, @Int64Rec(Result).Hi);
    finally CloseHandle(fHandle); end;
  end; { DSiFileSize }
like image 34
gabr Avatar answered Sep 21 '22 08:09

gabr


I'd like to mention few Pure Delphi ways. Though i think Deltics made a most speed-effective answer for Windows platform, yet sometimes you want just rely on RTL and also make portable code that would work in Delphi for MacOS or in FreePascal/Virtual Pascal/whatever.


There is FileSize function left from Turbo Pascal days.

  • http://turbopascal.org/system-functions-filepos-and-filesize
  • http://docwiki.embarcadero.com/CodeExamples/XE2/en/SystemFileSize_(Delphi)
  • http://docwiki.embarcadero.com/Libraries/XE2/en/System.FileSize

The sample above lacks "read-only" mode setting. You would require that to open r/o file such as one on CD-ROM media or in folder with ACLs set to r/o. Before calling ReSet there should be zero assigned to FileMode global var.

  • http://docwiki.embarcadero.com/Libraries/XE2/en/System.FileMode

It would not work on files above 2GB size (maybe with negative to cardinal cast - up to 4GB) but is "out of the box" one.


There is one more approach, that you may be familiar if you ever did ASM programming for MS-DOS. You Seek file pointer to 1st byte, then to last byte, and check the difference.
I can't say exactly which Delphi version introduced those, but i think it was already in some ancient version like D5 or D7, though that is just common sense and i cannot check it.
That would take you an extra THandle variable and try-finally block to always close the handle after size was obtained.

  • Sample of getting length and such
  • http://docwiki.embarcadero.com/Libraries/XE2/en/System.SysUtils.FileOpen
  • http://docwiki.embarcadero.com/Libraries/XE2/en/System.SysUtils.FileSeek

Aside from 1st approach this is int64-capable. It is also compatible with FreePascal, though with some limitations

  • http://www.freepascal.org/docs-html/rtl/sysutils/fileopen.html

You can also create and use TFileStream-typed object - which was the primary, officially blessed avenue for file operations since Delphi 1.0

  • http://www.freepascal.org/docs-html/rtl/classes/tfilestream.create.html
  • http://www.freepascal.org/docs-html/rtl/classes/tstream.size.html
  • http://docwiki.embarcadero.com/Libraries/XE2/en/System.Classes.TFileStream.Create
  • http://docwiki.embarcadero.com/Libraries/XE2/en/System.Classes.TStream.Size

As a side note, this avenue is of course integrated with aforementioned IOUtils unit.

  • http://docwiki.embarcadero.com/Libraries/XE3/en/System.IOUtils.TFile.OpenRead
like image 28
Arioch 'The Avatar answered Sep 21 '22 08:09

Arioch 'The