Since IO needs you to deal with streams, channels, and file descriptors that need to be closed properly, it is uncomfortable for Java developers to deal with them. Because of this, many Java programmers never bother doing clean-up, the laziness of just doing work and ignoring anything is really easy. For programmers who have never done system programming using C or C++, this habit is more visible.
To release the file descriptor held by this class as its limited resource and used in both socket connection and file handling, it is essential to close streams. A severe resource leak can also lead to an exception in the file descriptor.
Let’s see a code for copying a file from one directory to another directory in Java without using any third-party library.
Java
import java.io.*; class Main { public static void main(String args[]) throws FileNotFoundException { FileInputStream fis = null ; FileOutputStream fos = null ; try { fis = new FileInputStream( "input.txt" ); fos = new FileOutputStream( "output.txt" ); // code for reading from input stream and // writing to output stream } } finally { try { // careful to close streams in finally // block, but it’s not complete if (fis != null ) fis.close(); if (fos != null ) fos.close(); } catch (IOException e) { System.out.println( "Failed to close streams" ); } } } } |
Most of the code is al-right and even better than many Java programmers. but it has an error that could cause a resource leak in the Java program. If close() method of input stream will throw an Exception then output stream will not be closed, i.e. fos.close() will not even execute if fis.close() throws exception. This means the file descriptor held by OutputStream will never release causing a resource leak in the Java program. It’s not uncommon.
Here is the right way of closing InputStream and OutputStream in Java :
Java
import java.io.*; class Main { public static void main(String args[]) throws FileNotFoundException { InputStream is = null ; OutputStream os = null ; try { is = new FileInputStream( "../input/fxrates.txt" ); os = new FileOutputStream( "../output/fxrates.txt" ); // remaining code } finally { try { if (is != null ) is.close(); } catch (IOException e) { /* handle */ } try { if (os != null ) os.close(); } catch (IOException e) { /*handle */ } } } } |
If is.close() throws an IOException, this code would not fail to call os.close(), which would guarantee that the file descriptor kept by OutputStream is released.