Thursday 2 October 2008

Java: how not to make a mess of stream handling

This article was written with Java 6 in mind.
Updated 2008/12/16.

  /**
   * Writes "Hello, World!" to a file.
   */
  public static void main(String[] args) {
    try {
      byte[] data = "Hello, World!".getBytes("UTF-8");
      OutputStream out = new FileOutputStream("output.txt");
      //if write throws an error
      out.write(data);
      //then close will never be called! BUG!
      out.close();
    catch(IOException e) {
      System.err.println("ERROR");
      e.printStackTrace();
    }
  }

If you aren't careful with streams in Java, you end up with resource leaks. This article addresses some of the pitfalls of stream handling.

The examples that follow use implementations of OutputStream. Which output stream is not important - implementation details are encapsulated by the object and may change between Java versions. It is the developer's responsibility to honour the contract as per the documentation.

OutputStream.close(): Closes this output stream and releases any system resources associated with this stream. The general contract of close is that it closes the output stream. A closed stream cannot perform output operations and cannot be reopened.

New Java developers pick up pretty quickly that they have to close streams. Problems arise when they start thinking about how to do it.