Java Streams   «Prev  Next»

Lesson 6Flushing and closing
ObjectiveExamine when to flush and close streams.

Java IO Flushing and Closing

Many operating systems buffer writes to improve performance. In other words, rather than writing each byte as it is written, the bytes are accumulated in a buffer ranging in size from several bytes to several thousand bytes. Then, when the buffer fills up, all the data is written at once. The flush() method forces the data to be written whether or not the buffer is full.

public void flush() throws IOException

This is not the same as the buffering performed by a BufferedOutputStream. That buffering is handled by the Java runtime. This buffering is at the native OS level. However, a call to flush() should empty both buffers.


Java flush() method versus BufferedOutputStream

Question: How does the Java flush() method differ from the buffering performed by a BufferedOutputStream?
In Java, the flush() method and the buffering performed by a BufferedOutputStream are related but serve different purposes.
  1. flush() method: The flush() method is defined in both the OutputStream and Writer classes. It is used to force any buffered output data to be written to the underlying output destination immediately. The method is particularly useful when you want to make sure that data is written and visible to other processes or systems without closing the stream. For example, when writing data to a file or sending it over a network connection, the data might be buffered for efficiency reasons. Calling the flush() method ensures that any buffered data is written out, making it available to the receiving end, even if the stream is not yet closed.
  2. Buffering in BufferedOutputStream: BufferedOutputStream is a subclass of OutputStream that adds buffering capabilities to another output stream. It improves the efficiency of write operations by reducing the number of actual write calls to the underlying output stream (e.g., FileOutputStream, SocketOutputStream). When you write data to a BufferedOutputStream, it is stored in an internal buffer. Once the buffer is full, the entire content is written to the underlying output stream in a single call. This process significantly improves the performance of write operations, especially when working with small chunks of data or slow output devices, such as disks or network connections.

In summary, the flush() method is used to force any buffered data to be written to the underlying output destination, whereas the buffering performed by a BufferedOutputStream aims to improve the efficiency of write operations. When using a BufferedOutputStream, you might need to call the flush() method to ensure that all buffered data is written out before closing the stream or when you want to make the data available to other processes or systems.


If you only use a stream for a short time, you do not need to flush it explicitly. It should be flushed when the stream is closed. Of course this requires you to actually call the close() method instead, but generally you do not need to call both close() and flush().

Flushing and Closing Java Streams

All streams flush automatically when their buffers fill up, and all streams should be flushed when a program terminates normally.
However, if a program terminates abnormally, then buffers may not get flushed. In this case, unless there was an explicit call to flush() after each write, you can not be sure that the data that appears in the output properly indicates the point at which the program crashed. In fact, the program may have continued to run for some time past that point before it crashed.


You only need to explicitly flush an output stream if for some reason you need to make sure data is sent before you are through with the stream. For example, a program that sends a burst of data across the network periodically should flush after each burst of data is written to the stream. Flushing is often important when you are trying to debug a crashing program. System.out, System.err, and some (but not all) other print streams automatically flush after each call to println() and after each time a newline character ('\n') appears in the string being written. Whether autoflushing is enabled can be set in the PrintStream constructor.


OutputStream Class

The java.io.OutputStream class declares the three basic methods you need to write bytes of data onto a stream. It also has methods for closing and flushing streams.
public abstract void write(int b) throws IOException
public void write(byte[] data) throws IOException
public void write(byte[] data, int offset, int length) throws IOException
public void flush() throws IOException
public void close() throws IOException

OutputStream is an abstract class. Subclasses provide implementations of the abstract write(int b) method. They may also override the four nonabstract methods. For example, the FileOutputStream class overrides all five methods with native methods that know how to write bytes into files on the host platform. Although OutputStream is abstract, often you only need to know that the object you have is an OutputStream ; the more specific subclass of OutputStream is hidden from you. For example, the getOutputStream() method of java.net.URLConnection has the signature:

public OutputStream getOutputStream() throws IOException

Depending on the type of URL associated with this URLConnection object, the actual class of the output stream that's returned may be a
  1. sun.net.TelnetOutputStream,
  2. sun.net.smtp.SmtpPrintStream,
  3. sun.net.www.http.KeepAliveStream.

All you know as a programmer, and all you need to know, is that the object returned is in fact some instance of OutputStream. That is why the detailed classes that handle particular kinds of connections are hidden inside the sun packages. Furthermore, even when working with subclasses whose types you know, you still need to be able to use the methods inherited from OutputStream. And since methods that are inherited are not included in the online documentation, it's important to remember that they're there. For example, the java.io.DataOutputStream class does not declare a close() method, but you can still call the one it inherits from its superclass.

Given the following code :
1. import java.io.*;
3.   class ConsoleTest{
5.     public static void main(String args[]){
6.       Console con = System.console();
7.       char []c = con.readPassword("Enter the password : ");
8.       System.out.write("Your password is : ");
9.       for(int i :c){
10.       System.out.write(i);
11.       System.out.flush();
12.     }
13.   }
14. }
Note: assume that you have access to console object. Which option is true?
  1. Compilation succeeds and will prompt to enter a password and then it will print the password
  2. Compilation succeeds and it will prompt to enter a password but then it will not print the password.
  3. Compilation fails because there is no "write()" method defined.
  4. Compilation fails due to an error on line 8.
  5. Compilation fails due to an error on line 10.

Answer: D
Explanation:
In this code, we have tried to use the write() method of PrintStream. Although it has a set of overloaded write() methods, it does not have one to take a string as an argument. (Actually, it has, but it is marked as private.). So at line 8, trying to pass string to the write() method will cause compilation to fail. Hence, option D is correct because there is no need for defining a write() method. Option C is incorrect.
Because the code fails to compile, options A and B are incorrect. However, if we remove line 8 the answer would be option A. At, line 10, passing int to the write() method is legal because there is a method that takes int and then writes the character in the console according to the passed int value.

Writing Java Streams - Quiz

Click on the Quiz link below to take a brief multiple-choice quiz on writing streams.
Writing Java Streams - Quiz