package com.ronsoft.books.nio.channels; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.nio.channels.Channels; import java.io.IOException; /** * Test copying between channels. * * Created and tested: Dec 31, 2001 * Revised for NIO book, April 2002 * @author Ron Hitchens (ron@ronsoft.com) * @version $Id: ChannelCopy.java,v 1.4 2002/04/21 05:10:56 ron Exp $ */ public class ChannelCopy { /** * This code copies data from stdin to stdout. Like the 'cat' * command, but without any useful options. */ public static void main (String [] argv) throws IOException { ReadableByteChannel source = Channels.newChannel (System.in); WritableByteChannel dest = Channels.newChannel (System.out); channelCopy1 (source, dest); // alternatively, call channelCopy2 (source, dest); source.close(); dest.close(); } /** * Channel copy method 1. This method copies data from the src * channel and writes it to the dest channel until EOF on src. * This implementation makes use of compact() on the temp buffer * to pack down the data if the buffer wasn't fully drained. This * may result in data copying, but minimizes system calls. It also * requires a cleanup loop to make sure all the data gets sent. */ private static void channelCopy1 (ReadableByteChannel src, WritableByteChannel dest) throws IOException { ByteBuffer buffer = ByteBuffer.allocateDirect (16 * 1024); while (src.read (buffer) != -1) { // prepare the buffer to be drained buffer.flip(); // write to the channel, may block dest.write (buffer); // If partial transfer, shift remainder down // If buffer is empty, same as doing clear() buffer.compact(); } // EOF will leave buffer in fill state buffer.flip(); // make sure the buffer is fully drained. while (buffer.hasRemaining()) { dest.write (buffer); } } /** * Channel copy method 2. This method performs the same copy, but * assures the temp buffer is empty before reading more data. This * never requires data copying but may result in more systems calls. * No post-loop cleanup is needed because the buffer will be empty * when the loop is exited. */ private static void channelCopy2 (ReadableByteChannel src, WritableByteChannel dest) throws IOException { ByteBuffer buffer = ByteBuffer.allocateDirect (16 * 1024); while (src.read (buffer) != -1) { // prepare the buffer to be drained buffer.flip(); // make sure the buffer was fully drained. while (buffer.hasRemaining()) { dest.write (buffer); } // make the buffer empty, ready for filling buffer.clear(); } } }