0

Java 代码如下:

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();

        }
    }
}

实际结果:

写入:1017 读取:0 读取:1024 读取:44

第一次,方法read()读取 0 个字节。这并不酷。

我修改了我的代码:

    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();

    }

实际结果:

写入:1017 读取:1024 读取:44

它已经看起来更好了。谢谢你flip()

接下来,我放入缓冲区 String "Request",该 String 的长度为7,但方法write()返回1017

什么信息方法写入通道?

我不确定,该方法写了字符串"Request"

好的,我再次修改了我的代码:

    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();

    }

实际结果:

写:7

和代码崩溃了......

凭什么?我的错误在哪里?

谢谢。

4

2 回答 2

6

flip需要在从缓冲区读取数据之前调用该方法。该flip()方法将缓冲区重置limit为当前位置,并将缓冲区重置position为 0。

所以,如果你有 7 个字节的数据ByteBuffer,你的位置(从 0 开始)将flip()limit = 77 position = 0。现在,可以进行阅读了。

这是一个关于如何最好地使用的示例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);
    }
}
于 2012-07-20T15:17:32.723 回答
3

尽管它的(选择不当)名称,flip()它不是对称的。您必须在从缓冲区获取任何操作(写入或获取)之前调用它,然后调用其中一个compact()clear()之后将缓冲区恢复到准备好读取或放置的状态。

于 2012-07-20T19:43:42.267 回答