package LBJ2.io; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.WritableByteChannel; /** * This class implements an output stream that buffers output in a directly * allocated <code>ByteBuffer</code> before writing it to a channel. * * @author Nick Rizzolo **/ public class ChannelOutputStream extends OutputStream { /** The default capacity of {@link #buffer}. */ private static int defaultCapacity = 1 << 13; /** Holds data until it is written. */ protected ByteBuffer buffer; /** The channel where the data will be written. */ protected WritableByteChannel channel; /** * Creates the stream from the channel where the data will be written. * * @param out The channel where the data will be written. **/ public ChannelOutputStream(WritableByteChannel out) { this(out, defaultCapacity); } /** * Creates the stream from the channel where the data will be written and a * buffer size. * * @param out The channel where the data will be written. * @param size The buffer size. **/ public ChannelOutputStream(WritableByteChannel out, int size) { if (size < 0) size = 0; buffer = ByteBuffer.allocateDirect(size); channel = out; } /** * Writes the specified byte to this channel output stream. * * @param b The byte to be written. * @exception IOException Possible while {@link #flush}ing. **/ public synchronized void write(int b) throws IOException { if (buffer.position() == buffer.capacity()) flush(); buffer.put((byte) b); } /** * Writes <code>len</code> bytes from the specified byte array * starting at offset <code>off</code> to this channel output stream. * * @param b The data. * @param off The start offset in the data. * @param len The number of bytes to write. * @exception IOException Possible while {@link #flush}ing. **/ public synchronized void write(byte[] b, int off, int len) throws IOException { int r = buffer.capacity() - buffer.position(); if (len > r) { buffer.put(b, off, r); flush(); off += r; len -= r; r = buffer.capacity(); } while (len > r) { buffer.put(b, off, r); flush(); off += r; len -= r; } if (len > 0) buffer.put(b, off, len); } /** * Forces any buffered output bytes to be written to {@link #channel}. * * @exception IOException Possible while writing to {@link #channel}. **/ public synchronized void flush() throws IOException { buffer.flip(); channel.write(buffer); buffer.clear(); } /** * Flushes the {@link #buffer} and closes the {@link #channel}. * * @exception IOException Possible while closing {@link #channel}. **/ public void close() throws IOException { flush(); channel.close(); } }