Java io ugly try-finally block

前端 未结 12 1032
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-28 05:57

Is there a not so ugly way of treat the close() exception to close both streams then:

    InputStream in = new FileInputStream(inputFileName);
          


        
相关标签:
12条回答
  • 2020-11-28 06:46

    You have, in commons io, in IOUtils, some closeQuietly methods.

    0 讨论(0)
  • 2020-11-28 06:47

    Guava has very nice IO APIs that eliminate the need for this. For instance, your example would be:

    Files.copy(new File(inputFileName), new File(outputFileName));
    

    More generally, it uses the concept of InputSuppliers and OutputSuppliers to allow the InputStreams and OutputStreams to be created within its utility methods, allowing it full control over them so it can handle closing properly.

    Additionally, it has Closeables.closeQuietly(Closeable) which is basically the type of method most of the answers have suggested.

    The IO stuff in it is still in beta and subject to change, but it's worth checking out and even using, depending on what it is you're working on.

    0 讨论(0)
  • 2020-11-28 06:51

    You could implement a utility method:

    public final class IOUtil {
      private IOUtil() {}
    
      public static void closeQuietly(Closeable... closeables) {
        for (Closeable c : closeables) {
            if (c != null) try {
              c.close();
            } catch(Exception ex) {}
        }
      }
    }
    

    Then your code would be reduced to:

    try {
      copy(in, out);
    } finally {
      IOUtil.closeQuietly(in, out);
    }
    

    Additional

    I imagine there'll be a method like this in a 3rd party open-source library. However, my preference is to avoid unnecessary library dependencies unless I'm using a large portion of its functionality. Hence I tend to implement simple utility methods like this myself.

    0 讨论(0)
  • 2020-11-28 06:53

    Here is my answer hopefully much better

    https://stackoverflow.com/a/35623998/2585433

    try {
        fos = new FileOutputStream(new File("..."));
        bos = new BufferedOutputStream(fos);
        oos = new ObjectOutputStream(bos);
    }
    catch (Exception e) {
    }
    finally {
        Stream.close(oos,bos,fos);
    }
    
    
    class Stream {
    
    public static void close(AutoCloseable... array) {
        for (AutoCloseable c : array) {
            try {c.close();}
            catch (IOException e) {}
            catch (Exception e) {}
        }
      } 
    }
    
    0 讨论(0)
  • 2020-11-28 06:57

    This is the correct idom (and it works fine):

       InputStream in = null;
       OutputStream out = null;
       try {
           in = new FileInputStream(inputFileName);
           out = new FileOutputStream(outputFileName);
           copy(in, out);
       finally {
           close(in);
           close(out);
       }
    
      public static void close(Closeable c) {
         if (c == null) return; 
         try {
             c.close();
         } catch (IOException e) {
             //log the exception
         }
      }
    

    The reason this works fine is that the exception thrown before you got to finally will be thrown after your finally code finishes, provided that your finally code doesn't itself throw an exception or otherwise terminate abnormally.

    Edit: As of Java 7 (and Android SDK 19 - KitKat) there is now a Try with resources syntax to make this cleaner. How to deal with that is addressed in this question.

    0 讨论(0)
  • 2020-11-28 06:57

    One trick I sometimes use is to define a method called closeQuietly(Closeable) that tests to see if its argument is null then closes it, ignoring any exceptions. But you need to be a careful closing OutputStreams and Writers that way because they may actually throw an exception that matters; e.g. if the final flush fails.

    Things are likely to improve with Java 7. Reports are that it will have a new construct that provides a more concise way of handling managed resources; e.g. streams that need to be closed when they are finished with.

    Finally, you should be aware that your example has a bug. If the method call to open the second stream, the first stream will not be closed. The second open needs to be done inside the try block.

    0 讨论(0)
提交回复
热议问题