Closing Output Streams
When you're through with a stream, you should close it. This allows the operating system to free any resources associated with the stream. Exactly what these resources are depends on your platform and varies with the type of stream. However, many systems have finite resources. For example, on some personal computer operating systems, no more than several hundred files can be open at once. Multiuser operating systems have larger limits, but limits nonetheless.
To close a stream, invoke its close( ) method:
public void close( ) throws IOException
For example, again assuming out is an OutputStream, calling out.close( ) closes the stream and frees any underlying resources such as file handles or network ports associated with the stream.
Once you have closed an output stream, you probably can't write anything else onto that stream. Attempting to do so normally throws an IOException, though there are a few classes where this doesn't happen.
|
Not all streams need to be closedbyte array output streams do not need to be closed, for example. However, streams associated with files and network connections should always be closed when you're done with them. For example, if you open a file for writing and neglect to close it when you're through, then other processes may be blocked from reading or writing to that file. Often, files are closed like this:
try { OutputStream out = new FileOutputStream("numbers.dat"); // Write to the stream... out.close( ); } catch (IOException ex) { System.err.println(ex); }
However, this code fragment has a potential leak. If an IOException is thrown while writing, the stream won't be closed. It's more reliable to close the stream in a finally block so that it's closed whether or not an exception is thrown. To do this you need to declare the OutputStream variable outside the try block. For example:
// Initialize this to null to keep the compiler from complaining // about uninitialized variables OutputStream out = null; try { out = new FileOutputStream("numbers.dat"); // Write to the stream... } catch (IOException ex) { System.err.println(ex); } finally { if (out != null) { try { out.close( ); } catch (IOException ex) { System.err.println(ex); } } }
Variable scope and nested try-catch-finally blocks make this a little uglier, yet it's quite a bit safer. The code can be a little cleaner if you have the option of propagating any IOExceptions thrown rather than catching them; that is, if the method that contains this code is declared to throw IOException. In that case, a typical call to close( ) works like this:
// Initialize this to null to keep the compiler from complaining // about uninitialized variables OutputStream out == null; try { out = new FileOutputStream("numbers.dat"); // Write to the stream... } finally { if (out != null) out.close( ); }
2.3.1. The Closeable Interface
Java 5 added a Closeable interface that the OutputStream class implements:
package java.io; public interface Closeable { void close( ) throws IOException; }
InputStream, Channel, Formatter, and various other things that can be closed also implement this interface. Personally I've never figured out the use case that justifies this extra interface, but it's there if for some reason you want to write a method that accepts only arguments that can be closed, or some such.