Question

Java code below:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class Test {
    public static void main(String args[]) throws IOException {

        SocketChannel c = SocketChannel.open();
        c.connect(new InetSocketAddress("google.com", 80));

        ByteBuffer b = ByteBuffer.allocate(1024);
        b.put("Request".getBytes());

        System.out.println("Write: " + c.write(b));

        int i;
        while ((i = c.read(b)) != -1) {

            System.out.println("Read: " + i);
            b.clear();

        }
    }
}

Actual Result:

Write: 1017 Read: 0 Read: 1024 Read: 44

First time, method read() read 0 bytes. It is not cool.

I modified my code:

    b.put("Request".getBytes());

    System.out.println("Write: " + c.write(b));

    b.flip(); //I added this line
    int i;
    while ((i = c.read(b)) != -1) {

        System.out.println("Read: " + i);
        b.clear();

    }

Actual results:

Write: 1017 Read: 1024 Read: 44

It already looks better. Thanks flip() for this!

Next, I put to buffer String "Request", this String has length 7, but method write()returned 1017.

What information method wrote to channel?

I am not sure, that method wrote string "Request".

Ok, I modified my code again:

    b.put("Request".getBytes());

    b.flip(); // I added this line
    System.out.println("Write: " + c.write(b));

    b.flip();
    int i;
    while ((i = c.read(b)) != -1) {

        System.out.println("Read: " + i);
        b.clear();

    }

Actual results:

Write: 7

and code crashed...

By why? Where is my mistake?

Thanks.

Was it helpful?

Solution

The flip method needs to be called before reading data from the buffer. The flip() method, reset the buffer's limit to the current position and reset the buffer's position to 0.

So, if you have 7 byte of data in ByteBuffer, your position (starting from 0), would be 7. flip()'ing it, would make limit = 7, position = 0. Now, reading can occur.

Here's an example on how to best use flip():

public static final void nioCopy(ReadableByteChannel input, WritableByteChannel output) throws IOException {
    ByteBuffer buffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
    while (input.read(buffer) != -1) {
        //Flip buffer
        buffer.flip();
        //Write to destination
        output.write(buffer);
        //Compact
        buffer.compact();
    }

    //In case we have remainder
    buffer.flip();
    while (buffer.hasRemaining()) {
        //Write to output
        output.write(buffer);
    }
}

OTHER TIPS

Despite its (poorly chosen) name, flip() is not symmetric. You must call it before any operation that gets from the buffer (write or get), and call either compact() or clear() afterwards to put the buffer back into a state where it is ready for reading or putting.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top