Code example for ByteBuffer

Methods: hasArray, hasRemaining, isDirect, isReadOnly, position

0
        // status must be open and connected 
        checkOpenConnected(); 
        // target buffer must be not null and not readonly 
        checkWritable(target);
 
        if (!target.hasRemaining()) {
            return 0; 
        } 
 
        int readCount = 0;
        if (target.isDirect() || target.hasArray()) {
            readCount = readImpl(target);
            if (readCount > 0) {
                target.position(target.position() + readCount);
            } 
 
        } else { 
            byte[] readArray = new byte[target.remaining()];
            ByteBuffer readBuffer = ByteBuffer.wrap(readArray);
            readCount = readImpl(readBuffer);
            if (readCount > 0) {
                target.put(readArray, 0, readCount);
            } 
        } 
        return readCount;
    } 
 
    /** 
     * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer[], int, 
     *      int) 
     */ 
    @Override 
    public long read(ByteBuffer[] targets, int offset, int length)
            throws IOException { 
        if (length < 0 || offset < 0
                || (long) length + (long) offset > targets.length) {
            throw new IndexOutOfBoundsException();
        } 
 
        // status must be open and connected 
        checkOpenConnected(); 
 
        int totalCount = 0;
        for (int val = offset; val < length; val++) {
            // target buffer must be not null and not readonly 
            checkWritable(targets[val]);
            totalCount += targets[val].remaining();
        } 
 
        // read data to readBuffer, and then transfer data from readBuffer to 
        // targets. 
        ByteBuffer readBuffer = ByteBuffer.allocate(totalCount);
        int readCount;
        readCount = readImpl(readBuffer);
        int left = readCount;
        int index = offset;
        // transfer data from readBuffer to targets 
        byte[] readArray = readBuffer.array();
        while (left > 0) {
            int putLength = Math.min(targets[index].remaining(), left);
            targets[index].put(readArray, readCount - left, putLength);
            index++;
            left -= putLength;
        } 
        return readCount;
    } 
 
    /* 
     * read from channel, and store the result in the target. 
     */ 
    private int readImpl(ByteBuffer readBuffer) throws IOException {
        synchronized (readLock) {
            int readCount = 0;
            try { 
                begin(); 
                // timeout == 0 means block read. 
                // DEFAULT_TIMEOUT is used in non-block mode. 
                int timeout = isBlocking() ? 0 : DEFAULT_TIMEOUT;
                int start = readBuffer.position();
                int length = readBuffer.remaining();
                if (readBuffer.isDirect()) {
                    int address = AddressUtil.getDirectBufferAddress(readBuffer);
                    if (isConnected()) { 
                        readCount = networkSystem.recvConnectedDatagramDirect(
                                fd, null, address, start, length, timeout,
                                false); 
                    } else { 
                        readCount = networkSystem.receiveDatagramDirect(fd,
                                null, address, start, length, timeout, false);
                    } 
                } else { 
                    // the target is assured to have array. 
                    byte[] target = readBuffer.array();
                    start += readBuffer.arrayOffset();
                    if (isConnected()) { 
                        readCount = networkSystem.recvConnectedDatagram(fd,
                                null, target, start, length, timeout, false);
                    } else { 
                        readCount = networkSystem.receiveDatagram(fd, null,
                                target, start, length, timeout, false);
                    } 
                } 
                return readCount;
            } catch (InterruptedIOException e) {
                // InterruptedIOException will be thrown when timeout. 
                return 0; 
            } finally { 
                end(readCount > 0);
            } 
        } 
    } 
 
    /** 
     * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer) 
     */ 
    @Override 
    public int write(ByteBuffer source) throws IOException {
        // source buffer must be not null 
        checkNotNull(source);
        // status must be open and connected 
        checkOpenConnected(); 
        // return immediately if source is full 
        if (!source.hasRemaining()) {
            return 0; 
        } 
 
        ByteBuffer writeBuffer = null;
        byte[] writeArray = null;
        int oldposition = source.position();
        int result;
        if (source.isDirect() || source.hasArray()) {
            writeBuffer = source;
        } else { 
            writeArray = new byte[source.remaining()];
            source.get(writeArray);
            writeBuffer = ByteBuffer.wrap(writeArray);
        } 
        result = writeImpl(writeBuffer);
        if (result > 0) {
            source.position(oldposition + result);
        } 
        return result;
    } 
 
    /** 
     * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer[], int, 
     *      int) 
     */ 
    @Override 
    public long write(ByteBuffer[] sources, int offset, int length)
            throws IOException { 
        if (length < 0 || offset < 0
                || (long) length + (long) offset > sources.length) {
            throw new IndexOutOfBoundsException();
        } 
 
        // status must be open and connected 
        checkOpenConnected(); 
        int count = calculateByteBufferArray(sources, offset, length);
        if (0 == count) {
            return 0; 
        } 
        ByteBuffer writeBuf = ByteBuffer.allocate(count);
        for (int val = offset; val < length + offset; val++) {
            ByteBuffer source = sources[val];
            int oldPosition = source.position();
            writeBuf.put(source);
            source.position(oldPosition);
        } 
        writeBuf.flip();
        int result = writeImpl(writeBuf);
        int val = offset;
        int written = result;
        while (result > 0) {
            ByteBuffer source = sources[val];
            int gap = Math.min(result, source.remaining());
            source.position(source.position() + gap);
            val++;
            result -= gap;
        } 
        return written;
    } 
 
    /* 
     * Write the source. Return the count of bytes written. 
     */ 
    private int writeImpl(ByteBuffer buf) throws IOException {
        synchronized (writeLock) {
            int result = 0;
            try { 
                begin(); 
                int length = buf.remaining();
                int start = buf.position();
 
                if (buf.isDirect()) {
                    int address = AddressUtil.getDirectBufferAddress(buf);
                    result = networkSystem.sendConnectedDatagramDirect(fd,
                            address, start, length, isBound);
                } else { 
                    // buf is assured to have array. 
                    start += buf.arrayOffset();
                    result = networkSystem.sendConnectedDatagram(fd, buf
                            .array(), start, length, isBound);
                } 
                return result;
                // android-removed: bogus catch (SocketException e) and use of ErrorCodeException. 
            } finally { 
                end(result > 0);
            } 
        } 
    } 
 
    /* 
     * Do really closing action here. 
     */ 
    @Override 
    synchronized protected void implCloseSelectableChannel() throws IOException { 
        connected = false;
        if (null != socket && !socket.isClosed()) {
            socket.close();
        } else { 
            networkSystem.socketClose(fd);
        } 
    } 
 
    /** 
     * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking(boolean) 
     */ 
    @Override 
    @SuppressWarnings("unused") 
    protected void implConfigureBlocking(boolean blockingMode)
            throws IOException { 
        // Do nothing here. For real read/write operation in nonblocking mode, 
        // it uses select system call. Whether a channel is blocking can be 
        // decided by isBlocking() method. 
    } 
 
    /* 
     * Status check, must be open. 
     */ 
    private void checkOpen() throws IOException { 
        if (!isOpen()) {
            throw new ClosedChannelException();
        } 
    } 
 
    /* 
     * Status check, must be open and connected, for read and write. 
     */ 
    private void checkOpenConnected() throws IOException { 
        checkOpen(); 
        if (!isConnected()) { 
            throw new NotYetConnectedException();
        } 
    } 
 
    /* 
     * Buffer check, must not null 
     */ 
    private void checkNotNull(ByteBuffer source) {
        if (null == source) {
            throw new NullPointerException();
        } 
    } 
 
    /* 
     * Buffer check, must not null and not read only buffer, for read and 
     * receive. 
     */ 
    private void checkWritable(ByteBuffer target) {
        // including checking of NPE. 
        if (target.isReadOnly()) {
            throw new IllegalArgumentException();
        } 
    } 
 
    /*