is checking if a file object exists redudent and bad style when you have a try, catch block?

Tags: , ,



Is it overly redundant and considered bad style to check that the file object exists before a try catch. Since the FileNotFoundException would be called anyways if the file object did not exist?

    if (!in.exists()) {
      System.err.println("Missing important input files!");
      System.exit(1);
    }

    try {
        int [] numbers = new int[100];

        Scanner input = new Scanner(in);
        for (int i = 0; i < numbers.length; i++) {
            numbers[i] = input.nextInt();
        }
        input.close();

        Arrays.sort(numbers);

        PrintWriter output = new PrintWriter("output.txt");
        for (int i = 0; i < numbers.length; i++) {
            output.println(numbers[i]);
        }
        output.close();
    } catch (FileNotFoundException ex) {
        System.err.println("FileNotFoundException");
    }

Answer

Yes, the exists test is redundant. An implicit existence test happens within the Scanner. (Actually, it occurs in the syscall that opens the file.)

And it would difficult (and wrong headed) to avoid catching the IOException that new Scanner(File) declares. That would (IMO) be really bad style.

And there is also the point that there is a “race condition” between calling exists and then opening the file. It is conceivable that something else outside of the JVM could create or delete or rename the file in the small time between the test and the open attempt. This kind of thing has been exploited in privilege escalation attacks in the past.

These can be “taken as read”.

So, IMO, the only real point of dispute here is to whether it would be stylistically wrong (in this case) to rely on exceptions to check for file existence.


Some people will argue like this:

  1. Exceptions should not be used for flow control; (see https://wiki.c2.com/?DontUseExceptionsForFlowControl).

  2. Testing for a missing file is flow control.

  3. Therefore you shouldn’t use try / catch for this.

The counter argument to this is that “Exceptions should not be used for flow control” should really say “Exceptions should not be used for normal flow control”, and that dealing with edge-cases (such as missing files) is not normal flow control.

We can break this down by looking at the arguments against using exceptions for flow control. The main ones are:

  • Readabilitytry / catch code is more difficult to read than a simple test. I would argue that that doesn’t apply in this case. In this case you have to handle the exception anyway. The added exists test is just adding code, and therefore more code to read and less readable.

  • Efficiency – creating, throwing and catching an exception is more expensive in Java than a simple if test. There are two counters to that:

    • The efficiency of a single test most likely doesn’t matter. In this case the microseconds that would be potentially be saved is completely irrelevant.

    • In this case, we also have to take account of the cost of the redundant exists test that happens in the non-exceptional case. That is a syscall. It could well be more expensive than the potential saving by avoiding exception handling. And if we assume that the input file usually exists, then we are usually paying that performance penalty. (Do the math ….)

  • “I don’t like exceptions”1 – Well, yes, but that is not a valid stylistic argument so we can’t address it in stylistic terms.

A final counter argument is that if the Java designers had NOT intended exceptions to be used in the case where a required file is missing, then they would NOT have declared APIs to throw an exception. And they certainly wouldn’t have decided to make the exception checked.


1 – Or <insert_name_of_some_expert> thinks they are bad.



Source: stackoverflow