Recent

Author Topic: How to Capture a File Not Found Exception?  (Read 574 times)

StephenMilner

  • New Member
  • *
  • Posts: 15
How to Capture a File Not Found Exception?
« on: January 14, 2022, 05:06:15 pm »
I've got this snippet of code in a private class procedure which is called by the Class constructor.

When I deliberately pass a file that doesn't exist....

Code: Pascal  [Select][+][-]
  1.   try
  2.     try
  3.       AssignFile(Settings, SettingsFile);
  4.       Reset(Settings); // This generates the exception
  5.       //Statements
  6.     except
  7.       on e: EFileNotFoundException do // This code check fails and the else part is executed
  8.          writeln (DateToSTR(Date),':', TimeToSTR(Time),':', 'File Not Found :'+SettingsFile);
  9.       else
  10.         Raise; // This executes
  11.     end;
  12.   finally
  13.     try // I'm not sure this is the correct approach....
  14.       Close(Settings);
  15.     except
  16.       on E: Exception do writeln (DateToSTR(Date),':', TimeToSTR(Time),':', 'File Not Closed :'+SettingsFile); // This executes and writes to the console.
  17.     end;

The exception
Code: Pascal  [Select][+][-]
  1. EFileNotFoundException
doesn't appear to be the correct one.

The final exception raised is:
Code: Pascal  [Select][+][-]
  1. EInOutError: File not found

Should I use
Code: Pascal  [Select][+][-]
  1. EInOutError
instead of
Code: Pascal  [Select][+][-]
  1. EFileNotFoundException
?

How do I differentiate between other kinds of input/output errors in my exception handling?

I want code execution to terminate when the file isn't found.

GetMem

  • Hero Member
  • *****
  • Posts: 3646
Re: How to Capture a File Not Found Exception?
« Reply #1 on: January 14, 2022, 05:20:43 pm »
Old way:
Code: Pascal  [Select][+][-]
  1.   AssignFile(Settings, SettingsFile);
  2.   {$I-}
  3.   Reset(f);
  4.   {$I+}
  5.   if IOResult <> 0 then
  6.     Raise EFileNotFoundException.Create('File not found!');
  7.   //..


Modern way:
Code: Pascal  [Select][+][-]
  1.  if not FileExists(SettingsFile) then
  2.    Raise EFileNotFoundException.Create('File not found!');
  3.  //..
« Last Edit: January 14, 2022, 05:24:25 pm by GetMem »

StephenMilner

  • New Member
  • *
  • Posts: 15
Re: How to Capture a File Not Found Exception?
« Reply #2 on: January 14, 2022, 06:05:33 pm »
Thanks.

Thanks that should simplify things

Thaddy

  • Hero Member
  • *****
  • Posts: 11138
Re: How to Capture a File Not Found Exception?
« Reply #3 on: January 14, 2022, 06:27:51 pm »
Why not call FileExists() and do away with EFileNotFoundException completely?
Exceptions should be just what they are:exceptions. They should be avoided in all situations where an exceptionless codepath is possible.
In this case EFileNotFoundException  is even a bit silly since FileExists() exists.. ;D
A good programmer should never burden his/hers code with superfluous exceptions.
« Last Edit: January 14, 2022, 06:33:45 pm by Thaddy »
You have morons, I am one, and you have morons squared.

Kays

  • Sr. Member
  • ****
  • Posts: 398
  • Whasup!?
    • KaiBurghardt.de
Re: How to capture a file not found exception?
« Reply #4 on: January 14, 2022, 06:34:08 pm »
Old way: […]
I don’t think the “old way” would use exceptions at all. Besides, IOResult does have many other results. I think the expected functionality of software is to produce reasonable and at least somewhat understandable error messages.
Code: Pascal  [Select][+][-]
  1. program nonExistentFileDemo(input, output, stdErr);
  2. uses
  3.         sysUtils; { ❗ automagically converts all RTEs to exceptions }
  4. const
  5.         FN = '/tmp/blabla';
  6. resourceString
  7.         errorInvalidPath = 'Error: some component in `%0:s` inaccessible';
  8. var
  9.         FD: text;
  10. begin
  11.         assign(FD, FN); { `assignFile` only in objFPC mode (←objPas unit) }
  12.         {$push}
  13.         {$IOChecks off}
  14.         reset(FD);
  15.         {$pop}
  16.         case IOResult of
  17.                 0:
  18.                 begin
  19.                         { no error }
  20.                 end;
  21.                 2:
  22.                 begin
  23.                         writeLn(stdErr, format(errorInvalidPath, [FN]));
  24.                         halt(-1);
  25.                 end;
  26.                 otherwise
  27.                 begin
  28.                         halt(-1);
  29.                 end;
  30.         end;
  31. end.

Why not call FileExists() and do away with EFileNotFoundException completely?
TOCTOU: The file gets deleted after the successful check, but just before you actually open it for reading.
« Last Edit: January 14, 2022, 08:03:21 pm by Kays »
Yours Sincerely
Kai Burghardt

GetMem

  • Hero Member
  • *****
  • Posts: 3646
Re: How to Capture a File Not Found Exception?
« Reply #5 on: January 14, 2022, 06:57:26 pm »
@Kays
Quote
I don’t think the “old way” would use exceptions at all. Besides, IOResult does have many other results
I agree with the exception part, I wouldn't even use an exception here, but that is not my concern.
By old I was referring to IOResult, when I learned to programming in the 90', it was already obsolete.

PascalDragon

  • Hero Member
  • *****
  • Posts: 3652
  • Compiler Developer
Re: How to Capture a File Not Found Exception?
« Reply #6 on: January 14, 2022, 08:42:18 pm »
The exception
Code: Pascal  [Select][+][-]
  1. EFileNotFoundException
doesn't appear to be the correct one.

The final exception raised is:
Code: Pascal  [Select][+][-]
  1. EInOutError: File not found

Should I use
Code: Pascal  [Select][+][-]
  1. EInOutError
instead of
Code: Pascal  [Select][+][-]
  1. EFileNotFoundException
?

Correct. If I/O exceptions are enabled it's always converted to an EInOutError.

How do I differentiate between other kinds of input/output errors in my exception handling?

You can get the I/O result code from the exception with EInOutError.ErrorCode. For a list of error codes see here.

 

TinyPortal © 2005-2018