views:

234

answers:

3

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.

A: 

You can use simple workaround API call:

var
  LowCount,
  HighCount: integer;
...

  LowCount := GetCompressedFileSize('c:\test.txt', @HighCount);

The API call GetCompressedFileSize also works well for non-compressed files!

If you need the actual number of bytes of disk storage then you can call API GetCompressedFileSizeTransacted

GJ
This might not give you the answer you are expecting... "compressed" in this case doesn't mean just ZIP files etc. If the file you are querying resides on a compressible volume then you will get the size of actual storage used by the file on the disc after file system compression, not the size of the file contents (which sometimes might be what you need to know, but only quite rarely I should think). It also needs two variables to make the call and leaves you with the fiddly job of stitching lo and hi DWORD's together for files that are (or even just may be) > 4GB.
Deltics
+2  A: 

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).

  function FileSize(const aFilename: String): Int64;
  var
    info: TWin32FileAttributeData;
  begin
    result := -1;

    if NOT GetFileAttributesEx(PWideChar(aFileName), GetFileExInfoStandard, @info) then
      EXIT;

    result := info.nFileSizeLow or (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.

GetFileSize*Ex*() 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.

Deltics
-1: Your function doesn't work on commpessed files
GJ
Smasher didn't explain what kind of file size wonts to get.
GJ
For a compressed file (zip, rar, 7z etc) it will report the size of the archive in bytes, not the size of the decompressed contents. But for a ZIP file, the size of the file IS the size of the archive. For a file on a compressed volume it will report the size of the decompressed file, which is what you want because you are asking for the size of the storage object (the file) not the physical storage medium (the OS enforced compression). For files < 4GB the approach you suggest is quite simply more complicated unless you naively and incorrectly *assume* that all files are always < 4GB
Deltics
+1  A: 

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

gabr