java.nio.channels.CompletionHandler Example
This article introduces the CompletionHandler
and its basic usage. This interface is available since Java SE 7 as part of Java NIO 2 File API. This article’s example shows reading from a file using asynchronous file channel and using the completion handler to consume its result.
The example in this article is compiled and run in Windows OS environment. Note that Java SE 7 is required to run the code.
1. Introduction
CompletionHandler<V,A>
interface is defined in the java.nio.channels
package.
The type parameters:
- V – The result type of the I/O operation
- A – The type of the object attached to the I/O operation
This is a handler for consuming the result of an asynchronous I/O operation.
The asynchronous channels (AsynchronousFileChannel
, AsynchronousServerSocketChannel
and AsynchronousSocketChannel
) defined in the java.nio.channels
package allow a completion handler to be specified to consume the result of an asynchronous operation. The handler is used as a mechanism for monitoring the initiated asynchronous I/O operations. The handler is specified as a parameter and is invoked to consume the result of the I/O operation (read or write).
This interface has two methods to override. The completed()
method is invoked when the I/O operation completes successfully. The failed()
method is invoked if the I/O operations fails.
The example in this article shows the usage of a completion handler with asynchronous file channel’s read operation.
2. Read Operation with Completion Handler
In this example a text file is read using an asynchronous file channel and the result is consumed by a completion handler.
2.1. The input file
This is an existing text file.
String filePath = "readfile.txt"; Path path = Paths.get(filePath);
2.2. Create a channel
The AsynchronousFileChannel.open()
static method is used to create the channel. The method opens the file that is supplied to this method. By default the file is opened for read operation. The method throws IOException
.
AsynchronousFileChannel channel = AsynchronousFileChannel.open(path);
2.3. Create a buffer
Create a buffer using the ByteBuffer
‘s allocate()
static method, with initial capacity set to 1024.
ByteBuffer buffer = ByteBuffer.allocate(1024);
2.4. Read from the channel into the buffer
This explains the channel’s read operation and the consumption of its result by a completion handler.
AsynchronousFileChannel
‘s read()
method initiates an asynchronous read operation to read a sequence of bytes from this channel into the given buffer. The handler parameter is a completion handler that is invoked when the read operation completes (or fails). The result passed to the completion handler is the number of bytes read or -1 if no bytes could be read because the channel has reached end-of-stream.
The method doesn’t throw any checked exceptions.
currentThread = Thread.currentThread(); channel.read(buffer, 0, "Read operation ALFA", new CompletionHandler() { @Override public void completed(Integer result, Object attachment) { System.out.println(attachment + " completed and " + result + " bytes are read. "); currentThread.interrupt(); } @Override public void failed(Throwable e, Object attachment) { System.out.println(attachment + " failed with exception:"); e.printStackTrace(); currentThread.interrupt(); } }); try { currentThread.join(); } ...
Note, in the above code snippet, Thread
class’s currentThread()
static method returns the currently executing thread. In this case, the value (Thread.getName()
) will be the main
– that is the application’s main thread.
The channel’s read()
method parameters are:
- The buffer is the byte buffer into which the file contents are read
- The value 0 is the position from where the file’s data transfer starts
- “Read operation ALFA” is a
String
attachment object passed on to the completion handler methods - The completion handler for consuming the result
The channel’s read()
method is invoked asynchronously. The read operation runs, completes and one of the completion handler methods is executed.
The Thread
‘s join()
method blocks the current thread (main), until interrupted. The handler’s methods execute the initiating thread’s (main) interrupt()
method. This will make the main thread’s state runnable again.
2.5. Print the buffer contents
After the read operation the buffer’s position value is the number of bytes read. The buffer’s flip()
method sets the position to zero.
buffer.flip(); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); }
2.6. Clear buffer and close
The buffer’s clear()
method makes a buffer ready for a new sequence of channel-read: It sets the limit to the capacity and the position to zero.
buffer.clear(); channel.close();
The channel’s close()
method closes this channel. This method throws IOException
.
3. The Code and the Output
The following is the complete code for the example showing the reading from a file using asynchronous file channel, and using a completion handler to consume the result of the read operation.
ReadExample.java
import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousFileChannel; import java.nio.channels.CompletionHandler; import java.nio.file.Paths; import java.nio.file.Path; import java.io.FileReader; import java.io.BufferedReader; public class ReadExample { private Thread currentThread; public static void main (String [] args) throws Exception { new ReadExample().readFile(); } private void readFile() throws IOException { String filePath = "readfile.txt"; printFileContents(filePath); Path path = Paths.get(filePath); AsynchronousFileChannel channel = AsynchronousFileChannel.open(path); ByteBuffer buffer = ByteBuffer.allocate(1024); currentThread = Thread.currentThread(); channel.read(buffer, 0, "Read operation ALFA", new CompletionHandler() { @Override public void completed(Integer result, Object attachment) { System.out.println(attachment + " completed and " + result + " bytes are read. "); currentThread.interrupt(); } @Override public void failed(Throwable e, Object attachment) { System.out.println(attachment + " failed with exception:"); e.printStackTrace(); currentThread.interrupt(); } }); System.out.println ("Waiting for completion..."); try { currentThread.join(); } catch (InterruptedException e) { } buffer.flip(); System.out.print("Buffer contents: "); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } System.out.println(" "); buffer.clear(); channel.close(); } private void printFileContents(String path) throws IOException { FileReader fr = new FileReader(path); BufferedReader br = new BufferedReader(fr); String textRead = br.readLine(); System.out.println("File contents: "); while (textRead != null) { System.out.println(" " + textRead); textRead = br.readLine(); } fr.close(); br.close(); } }
The output is:
File contents: All the way from the inquisitive solarium on the top floor to the garrulous kitchen in the basement, little groups - convalescents in wheeled chairs, nurses with tardy trays, lean internes on rubber soles, grizzled orderlies trailing damp mops - met to whisper and separated to disseminate the bad news. Doctor Hudson was on the verge of a collapse. * Waiting for completion... Read operation ALFA completed and 352 bytes are read. Buffer contents: All the way from the inquisitive solarium on the top floor to the garrulous kitchen in the basement, little groups - convalescents in wheeled chairs, nurses with tardy trays, lean internes on rubber soles, grizzled orderlies trailing damp mops - met to whisper and separated to disseminate the bad news. Doctor Hudson was on the verge of a collapse. *
From the output:
- File contents: … This is the text in the file.
- Waiting for completion… This is displayed while the file read is in progress.
- Read operation ALFA completed and 352 bytes are read. The channel’s read operation is complete and the completion handler’s
completed()
method runs. - Buffer contents: All the way from the inquisitive solarium … The bytes in the buffer. Note this is the same as the file contents. The file had 352 bytes of text, and the buffer size was 1024. All the file contents are read in one read.
NOTES
See section 4 of the article java.nio.channels.AsynchronousFileChannel Example for the usage of completion handler with the asynchronous write operation.
4. Download Java Source Code
This was an example of java.nio.channels.CompletionHandler
You can download the full source code of this example here: CompletionHandlerExample.zip