brain storm
brain storm

Reputation: 31262

Can closing a File fail?

I saw this code and wondered why in.close() was done in the finally block. The main point of try-with resources is that it closes the resources correct.

  File file = new File(FILE_NAME);
          FileInputStream in = null;

        try (in = new FileInputStream(file)){
            //do something
        } catch (final FileNotFoundException e) {
            log.log(Level.WARNING, "file not found, " + file.getAbsolutePath(), e);
        } catch (final IOException e) {
            log.log(Level.WARNING, "cannot access the file for reading", e);
        } finally {
            if (in != null){
                try {
                    in.close();
                } catch (final IOException e) {
                    log.log(Level.WARNING, "Attempt to close file failed.", e);
                }
            }
        }

Will there be a situation where a file can be opened but cannot be closed using try-with-resources in Java?

Upvotes: 2

Views: 1131

Answers (4)

Pyranja
Pyranja

Reputation: 3599

The finally block in your example is redundant. The try-with-resources statement is basically doing the same (but is significantly less error prone!). As it is executed after the try-with-resources statement attempts to close the resources, the finally block is essentially a noop (there may be the possibility of a second attempt to close a resource succeeding after the first fails - but if this is even possible, it is a negligible edge case and certainly non-deterministic).

Note that the catch blocks in contrast are significant. The attempt to close resources will take place before a catch block is activated, leading to the possibility that more than one exception occurs. This is solved by using suppressed exceptions. Therefore, if using the resource fails, there will nonetheless be an attempt to close it properly (which will often fail too) and catch blocks will receive the first (most likely root) cause, instead of the exception thrown while closing hiding the first error.

For more informations see the official documentation!

Upvotes: 4

Nathaniel Jones
Nathaniel Jones

Reputation: 1849

Yes, this can happen. The method signature for close() does throw an IOException, so a good programmer should be prepared for this eventuality.

Often, the catch block will be moved outside the method, which makes handling it somewhat easier and cleaner looking. For example:

public static void main(String[] args)
{
    try {
         readFile(new File("MyFile.txt"));
    } catch (IOException e) {
         /* handle the exception */
    }
}

private static void readFile(File file) throws IOException
{
    FileInputStream in = null;

    try {
        in = new FileInputStream(file);
        /* Read the file.  THIS MIGHT FAIL! */
    } finally {
        if (in != null) /* Check this because new FileInputStream() could have failed */
            in.close(); /* If this throws and exception, it will be handled by main() */
    }
}

Upvotes: 1

Costi Ciudatu
Costi Ciudatu

Reputation: 38235

I would do a simple test with some removable storage (USB stick, for instance):

Just write a program that opens a FileInputStream with a file from the USB stick and then prompts "Please remove the storage device", waits for an <Enter> and then tries in.close(). I would bet some IOException would be thrown.

Upvotes: 1

This is not exclusive to files, it happens in general with I/O.

The Java API specs that the close() method of InputStream may launch an exception if "An I/O error occurs"

So yes, it can happen, that behaviour generates that funny (or not so funnty) try-catch-finally-try-catch blocks.

Upvotes: 1

Related Questions