How should an InputStream and an OutputStream be closed?

mooongcle picture mooongcle · Nov 5, 2010 · Viewed 11.1k times · Source

I'm using the following code to close an InputStream and an OutputStream from a connection to a server:

try {
        if (mInputStream != null) {
            mInputStream.close();
            mInputStream = null;
        }

        if (mOutputStream != null) {
            mOutputStream.close();
            mOutputStream = null;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

However, the streams are not closing, they are still alive. If I connect again there are two different InputStreams. No exception is being caught in the catch section.

What am I doing wrong?

Answer

Skylar Sutton picture Skylar Sutton · Nov 5, 2010

Edit: Added the Java 8 try-with-resources example at the bottom, since the language has evolved since originally posted.

If you are using Java 7 (or lower), there are two problems with your posted code:

  1. The .close() calls should be handled in a finally block. This way they will ALWAYS be closed, even if it fell into a catch block somewhere along the way.
  2. You need to handle EACH .close() call in its own try/catch block or you could leave one of them stranded open. If your attempt to close the input stream failed you would be skipping over the attempt to close the output stream.

You want something more like this:

    InputStream mInputStream = null;
    OutputStream mOutputStream = null;
    try {
        mInputStream = new FileInputStream("\\Path\\MyFileName1.txt");
        mOutputStream = new FileOutputStream("\\Path\\MyFileName2.txt");
        //... do stuff to your streams
    }
    catch(FileNotFoundException fnex) {
        //Handle the error... but the streams are still open!
    }
    finally {
        //close input
        if (mInputStream != null) {
            try {
                mInputStream.close();
            }
            catch(IOException ioex) {
                //Very bad things just happened... handle it
            }
        }
        //Close output
        if (mOutputStream != null) {
            try {
                mOutputStream.close();
            }
            catch(IOException ioex) {
                //Very bad things just happened... handle it
            }
        }
    }

If you are using Java 8+, you don't need any of the catch/finally noise. You can use the try-with-resources syntax and Java will close the resource for you whenever and however you leave the block:

    try(InputStream mInputStream = new FileInputStream("\\Path\\MyFileName1.txt")) {
        try(OutputStream mOutputStream = new FileOutputStream("\\Path\\MyFileName2.txt")) {
        //... do stuff to your streams
    }
}