1

I want to check if a file exists and if exists whether it is empty or not.

I can handle file exists;

if FileExists(fileName) then

else
   ShowMessage('File Not Exists');

How can I test for an empty file?

Dale K
  • 25,246
  • 15
  • 42
  • 71
Dauezevy
  • 1,012
  • 4
  • 22
  • 46

3 Answers3

6

As @TLama suggested, following function returns true if the file is found and the size is zero.

function FileIsEmpty(const FileName: String): Boolean;
var
  fad: TWin32FileAttributeData;
begin
  Result := GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @fad) and
            (fad.nFileSizeLow = 0) and (fad.nFileSizeHigh = 0);
end;
LU RD
  • 34,438
  • 5
  • 88
  • 296
4

Test for a file size equal to zero. To see how to find the size of a file, refer to this question: Getting size of a file in Delphi 2010 or later?

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • @Abelisto you can use FindFirst also – David Heffernan May 12 '15 at 06:28
  • 5
    I'd use just that [`GetFileAttributesEx`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa364946%28v=vs.85%29.aspx) fn (with no `FileExists`). If it fails with [`ERROR_FILE_NOT_FOUND`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382%28v=vs.85%29.aspx#ERROR_FILE_NOT_FOUND) error, the file does not exist. If succeeds, you can grab the size and check for 0. – TLama May 12 '15 at 06:37
  • @TLama You should convert this to an answer. I haven't seen such aproach being used yet. – SilverWarior May 12 '15 at 07:02
  • @TLama I think it is plausible that some other error could be deemed "file not found". For instance, can ERROR_PATH_NOT_FOUND be returned? – David Heffernan May 12 '15 at 07:19
  • About the error you'll be right. However, you can skip the specific error checking (since you are going to get that file info, that is the aim). So if the function succeeds, you simply know that the file exists and that you obtained the queried information. Which meets the asked criteria by a single function call. – TLama May 12 '15 at 07:42
  • @TLama Since Delphi has become a cross-platform it is not so good to use OS-dependent API instead of framework capabilities. But if developer sure that his soft will be win only - it is the most optimal solution. – Abelisto May 12 '15 at 08:21
  • @Abelisto, that's right. I'm not taking this into account simply because I'm not taking Delphi as a serious tool for cross platform development (and I'm afraid to add *yet*). – TLama May 12 '15 at 08:28
0
var
  sr: TSearchRec;
begin
  if FindFirst('filename', faAnyFile, sr) = 0 then // If file exists ...
  try
    Result.size := sr.Size; // Check here is sr.Size = 0
    Result.date := FileDateToDateTime(sr.Time);
  finally
    FindClose(sr);
  end;
end;

Update: As more clear answer, there is complete function:

function FileExistsAndEmpty(const AFileName: string): Boolean;
var
  sr: TSearchRec;
begin
  Result := FindFirst(AFileName, faAnyFile, sr) = 0;
  if Result then begin // file exists ...
    Result := sr.Size = 0;
    FindClose(sr);
  end;
end;    
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Abelisto
  • 14,826
  • 2
  • 33
  • 41
  • Can't you clean this up? There's absolutely no explanation, just some inlined code, only some of which is relevant. What is `Result`? Why do you care about the date? You should teach the user good habits. Encapsulate this in a function with a meaningful name. – David Heffernan May 12 '15 at 08:30
  • @DavidHeffernan Sorry, it was just paste-copy from much more complex function. Answer was expanded. – Abelisto May 12 '15 at 08:38
  • @DavidHeffernan About the last editing. resources allocated for `sr` is not dependent to `FindFirst` result, as I know. After calling `FindFirs` it might be to free in any case. I spent a lot of time to find memory leaks related to such code :o) – Abelisto May 12 '15 at 08:54
  • 1
    No, that is not correct. My edit is accurate. Only call `FindClose` if `FindFirst` succeeds. I'm now going to downvote you because of your revert. You've made the answer worse now. Perhaps you should read the first block of code in your answer and consider whether `FindClose` is called if `FindFirst` fails. – David Heffernan May 12 '15 at 09:13
  • @DavidHeffernan Yes you are absolutely right. It is because I trying to paste to answer complete but much more complex code and delete unusable parts of it. Just lost in my code. In any case, after first calling `FindFirst` `TSearchRec` parameter must be released. – Abelisto May 12 '15 at 09:24
  • 2
    No. Only if `FindFirst` succeeds should `FindClose` be called. As you do in the first block of code. My edit was accurate and you should not have reverted it. – David Heffernan May 12 '15 at 09:26
  • @DavidHeffernan Reviewing my answers, you are right. Thanks for attention. However using `FindFirst` is platform-independent and much simpler so it is at least -1 for me but it is +1 for my answer :) Good luck. – Abelisto Jun 16 '15 at 11:21