Java File Read via ByteBuffer channelCopy(@Nonnull @WillNotClose final ReadableByteChannel aSrc, @Nonnull @WillNotClose final WritableByteChannel aDest)

Here you can find the source of channelCopy(@Nonnull @WillNotClose final ReadableByteChannel aSrc, @Nonnull @WillNotClose final WritableByteChannel aDest)

Description

Copy all content from the source channel to the destination channel.

License

Apache License

Parameter

Parameter Description
aSrc Source channel. May not be <code>null</code>. Is not closed after the operation.
aDest Destination channel. May not be <code>null</code>. Is not closed after the operation.

Return

The number of bytes written.

Declaration

@Nonnegative
public static long channelCopy(@Nonnull @WillNotClose final ReadableByteChannel aSrc,
        @Nonnull @WillNotClose final WritableByteChannel aDest) throws IOException 

Method Source Code

//package com.java2s;
/**/*from w w  w  .  j a va  2 s.  c o m*/
 * Copyright (C) 2006-2013 phloc systems
 * http://www.phloc.com
 * office[at]phloc[dot]com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.IOException;
import java.nio.ByteBuffer;

import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;

import javax.annotation.WillNotClose;

public class Main {
    private static final boolean USE_COPY_V1 = true;

    /**
     * Copy all content from the source channel to the destination channel.
     *
     * @param aSrc
     *        Source channel. May not be <code>null</code>. Is not closed after
     *        the operation.
     * @param aDest
     *        Destination channel. May not be <code>null</code>. Is not closed
     *        after the operation.
     * @return The number of bytes written.
     */
    @Nonnegative
    public static long channelCopy(@Nonnull @WillNotClose final ReadableByteChannel aSrc,
            @Nonnull @WillNotClose final WritableByteChannel aDest) throws IOException {
        if (aSrc == null)
            throw new NullPointerException("sourceChannel");
        if (!aSrc.isOpen())
            throw new IllegalArgumentException("sourceChannel is not open!");
        if (aDest == null)
            throw new NullPointerException("desitnationChannel");
        if (!aDest.isOpen())
            throw new IllegalArgumentException("desitnationChannel is not open!");

        long nBytesWritten;
        if (USE_COPY_V1)
            nBytesWritten = _channelCopy1(aSrc, aDest);
        else
            nBytesWritten = _channelCopy2(aSrc, aDest);
        return nBytesWritten;
    }

    /**
     * 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.<br>
     * Source: Java NIO, page 60
     *
     * @param aSrc
     *        Source channel. May not be <code>null</code>. Is not closed after
     *        the operation.
     * @param aDest
     *        Destination channel. May not be <code>null</code>. Is not closed
     *        after the operation.
     * @return The number of bytes written.
     */
    @Nonnegative
    private static long _channelCopy1(@Nonnull @WillNotClose final ReadableByteChannel aSrc,
            @Nonnull @WillNotClose final WritableByteChannel aDest) throws IOException {
        long nBytesWritten = 0;
        final ByteBuffer aBuffer = ByteBuffer.allocateDirect(16 * 1024);
        while (aSrc.read(aBuffer) != -1) {
            // Prepare the buffer to be drained
            aBuffer.flip();

            // Write to the channel; may block
            nBytesWritten += aDest.write(aBuffer);

            // If partial transfer, shift remainder down
            // If buffer is empty, same as doing clear()
            aBuffer.compact();
        }

        // EOF will leave buffer in fill state
        aBuffer.flip();

        // Make sure that the buffer is fully drained
        while (aBuffer.hasRemaining())
            nBytesWritten += aDest.write(aBuffer);

        return nBytesWritten;
    }

    /**
     * Channel copy method 2. This method performs the same copy, but assures the
     * temporary 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.<br>
     * Source: Java NIO, page 60
     *
     * @param aSrc
     *        Source channel. May not be <code>null</code>. Is not closed after
     *        the operation.
     * @param aDest
     *        Destination channel. May not be <code>null</code>. Is not closed
     *        after the operation.
     * @return The number of bytes written.
     */
    private static long _channelCopy2(@Nonnull @WillNotClose final ReadableByteChannel aSrc,
            @Nonnull @WillNotClose final WritableByteChannel aDest) throws IOException {
        long nBytesWritten = 0;
        final ByteBuffer aBuffer = ByteBuffer.allocateDirect(16 * 1024);
        while (aSrc.read(aBuffer) != -1) {
            // Prepare the buffer to be drained
            aBuffer.flip();

            // Make sure that the buffer was fully drained
            while (aBuffer.hasRemaining())
                nBytesWritten += aDest.write(aBuffer);

            // Make the buffer empty, ready for filling
            aBuffer.clear();
        }
        return nBytesWritten;
    }
}

Related

  1. blockingRead(SocketChannel so, long timeout, int bytes)
  2. channelCopy2(ReadableByteChannel src, WritableByteChannel dest)
  3. ClientReadWithBlock(SocketChannel sc)
  4. ClientReadWithWait(SocketChannel sc)
  5. copy(final ReadableByteChannel src, final WritableByteChannel dest)