Should I use method close or closeQuietly to close an output stream?
Asked Answered
W

4

12

When we need close an output stream, we have two choices.

  1. closeQuietly means close a stream with no exception throwing up.

    try {
        close(out)
    } catch(IOException e) {
    }
    
  2. close

    try {
        close(out)
    } catch(IOException e) {
        throw anException;
    }
    

as known, output stream will write a/several chars into the end of file when closing, if these writing goes wrong, the file also can't be open correctly such as ZipoutputStream.

if I use the first one, I will get some risk of fail closing. if I use the second one, it will let my code unfriendly.

Could someone give me some advices?

So sorry for describing the issue unclearly.

I meant that how to get an IO operation safely. if a resource's release gets failed, it would let caller know.

Thanks for all your answer. And especially thank @Don Roby for giving me a link which contains the best answer answered by @Fabian Barney

Warn answered 4/6, 2013 at 10:21 Comment(2)
possible duplicate of Is it safe to use Apache commons-io IOUtils.closeQuietly?Amari
catch(IOException e) { throw anException; } is pointless - you'd need to declare throws IOException to do that, so you might as well skip the try/catchCoequal
B
17

Since Java 7 IOUtils.closeQuietly became outdated and the only reasonable solution is try-with-resources which closes resources automatically

try (InputStream is = new FileInputStream(file)) {
    ...
}

Note that it also solves problem with correctly opening / closing more than one resource

try (InputStream is = new FileInputStream(infile); OutputStream out = new FileOutputStream(outfile)) {
   ...          
}

And it also does not suppress IOException that close() may throw, which is exactly what closeQuietly does.

Ballroom answered 4/6, 2013 at 10:24 Comment(0)
B
2

Some implementations of close() may include other logic like writing final bytes or flush()'ing data. Example is FilterOutputStream.

Now imaging a situation when stream is based on network channel or external USB drive. Both may disappear at any time. It could happen when executing close().

So my opinion: catch IOException and throw your application-specific exception with included cause-exception, like:

} catch (IOException e)
{
    throw new IOManagementException(e);
}

If you are stick on not to throwing exception, then log if with ERROR status at least.

if not done, it may result in very hard to analyze bug reports or strange behavior.

Boyd answered 4/6, 2013 at 10:36 Comment(1)
it's a good answer, but it will let my code unfriendly. I have known another solution, it is that try {..... out.close();} catch(IOException e) {throw a exception;} finally {IOUtils.closeQuietly(out)}Warn
A
0

As a rule of thumb, I never swallow exceptions, so depending on the logic required by the code I am writing, I might

  1. Log the exception:

    try {
      close(out);
    } catch(IOException e) {
      // log the exception
      log.info("An error has occurred during stream closing: {}", e);
    }
    
  2. Wrap it an throw it further

    try {
       close(out);
    } catch(IOException e) {
       throw new MyException(e);
    }
    

Since JDK 7 is around, I prefer (as mentioned by Evgeniy) to use try-with-resources:

try (OutputStream out = // create output stream) {
   // do the writing
} // at this point the stream is closed

This will close in an appropriate and safe manner the stream you are dealing with.

Anaphora answered 4/6, 2013 at 10:46 Comment(0)
C
0

Clean code is good thing but where ever compromising it can give you better results like maintenance, Debugging in this case we should do that. It can be done in a better way like custom exception or using Java7 feature as suggested above but the cost of writing few more line is worth it as per my experience.

Cockloft answered 4/6, 2013 at 10:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.