简体   繁体   English

Java NIO。 为什么flip()方法会破坏我的程序?

[英]Java NIO. Why flip() method breaks my program?

Java code below: 下面的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();

        }
    }
}

Actual Result: 实际结果:

Write: 1017 Read: 0 Read: 1024 Read: 44 写:1017读:0读:1024读:44

First time, method read() read 0 bytes. 第一次,方法read()读取0个字节。 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 写:1017读:1024读:44

It already looks better. 它看起来已经更好了。 Thanks flip() for this! 感谢flip()

Next, I put to buffer String "Request" , this String has length 7 , but method write() returned 1017 . 接下来,我将缓冲区字符串“ Request”放入缓冲区,该字符串的长度为7 ,但是方法write()返回1017

What information method wrote to channel? 哪种信息方法写给渠道?

I am not sure, that method wrote string "Request" . 我不确定,该方法写了字符串“ 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 写:7

and code crashed... 代码崩溃了...

By why? 为什么? Where is my mistake? 我的错误在哪里?

Thanks. 谢谢。

The flip method needs to be called before reading data from the buffer. 从缓冲区读取数据之前 ,需要调用flip方法。 The flip() method, reset the buffer's limit to the current position and reset the buffer's position to 0. flip()方法,将缓冲区的limit重置为当前位置,并将缓冲区的position重置为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 . 因此,如果ByteBuffer有7个字节的数据,则您的位置(从0开始)为flip()将其设为limit = 7position = 0 Now, reading can occur. 现在,可以进行阅读了。

Here's an example on how to best use flip() : 这是一个关于如何最好地使用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);
    }
}

Despite its (poorly chosen) name, flip() is not symmetric. 尽管其名称(选择不当), flip()还是不对称的。 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. 您必须在从缓冲区进行的任何操作(写入或获取)之前调用它,然后再调用compact()clear()将缓冲区放回可以读取或放置的状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM