28

我知道 flip() 将当前缓冲区位置设置为 0,并将限制设置为前一个缓冲区位置,而 rewind() 只是将当前缓冲区位置设置为 0。

在下面的代码中,我使用 rewind() 或 flip() 得到相同的结果。

byte b = 127;
bb.put(b);
bb.rewind();//or flip();

System.out.println(bb.get());
bb.rewind();// or flip();
System.out.println(bb.get());

你能给我一个真实的例子,说明这两种方法的区别真的很重要吗?提前致谢。

4

6 回答 6

19

从源代码来看,它们非常相似。您可以看到以下内容:

public final Buffer flip() {
    limit = position;
    position = 0;
    mark = -1;
    return this;
}

public final Buffer rewind() {
    position = 0;
    mark = -1;
    return this;
}

所以不同之处在于将 theflip设置limitposition,而rewind不是。假设你分配了一个 8 字节的缓冲区,你已经用 4 个字节填充了缓冲区,那么位置设置为 3,如下所示:

    [ 1  1  1  1  0  0  0  0]
               |           |
flip           limit       |
rewind                     limit

因此rewind,刚刚使用的限制已适当设置。

于 2017-07-04T12:15:21.593 回答
17

它们根本不等价。

AByteBuffer通常准备好read()(或准备好put())。

flip()使它准备好write()(或get())。

rewind()并在(或)compact()之后再次clear()准备好。read()/put()write()get()

于 2013-05-09T12:33:20.570 回答
4

rewind( ) 方法类似于flip( ) 但不影响限制。它只是将位置设置回 0。您可以使用 rewind() 返回并重新读取已经翻转的缓冲区中的数据。一个常见的情况是:使用flip()后,你从缓冲区读取数据,你想重新读取数据,这个方法可以工作。

于 2016-02-21T07:51:41.870 回答
1

这是一个示例,两者将产生不同的结果。如您所说,两者都将位置设置为0,两者的区别在于翻转将限制设置为上一个位置。

因此,对于翻转,如果您正在写入 (put),读取 (get) 的限制将成为您写入的最后一个元素的位置。如果您尝试阅读更多内容,它将引发异常。

倒带使限制保持不变。假设它处于容量(缓冲区大小),它将让您继续读取超出实际写入的数据,在这种情况下读取缓冲区初始化的初始零。

ByteBuffer bb = ByteBuffer.allocateDirect(2);
byte b = 127;
bb.put(b);
bb.rewind();//or flip();

System.out.println(bb.get());  // will print 127 in either case
System.out.println(bb.get());  // will print 0 for rewind, BufferUnderflow exception for flip
于 2016-09-18T18:22:46.577 回答
1

缓冲区具有位置、限制和容量属性。您可以在创建缓冲区时为 n 个元素分配空间。这里n是容量。分配缓冲区后,位置设置为 0,限制设置为容量。

如果您用 nx 个元素填充缓冲区,则位置将设置为 nx。缓冲区在 nx 之后将有空元素。

如果此时要排空缓冲区并且也只需要非空值,则需要将当前位置的限制设置为零并将位置设置为零。使用 hasRemaining(),您可以获取直到 nx 的元素。翻转设置限制和位置属性,如上所述。

翻转和倒带的区别在于翻转将位置设置为 0 并将限制设置为活动内容。方法 rewind 只是将位置设置为 0。

欲了解更多信息http://www.zoftino.com/java-nio-tutorial

于 2018-05-23T05:13:04.000 回答
0

@user963241 为@EJP 的答案添加更多颜色。

flip() 使其为 write() (或 get())做好准备

get() 示例;

您可能希望从缓冲区读取数据(假设您最初将其存储在其中)并将其用于其他用途,例如转换为字符串并对其进行操作以供进一步使用。

ByteBuffer buf = ByteBuffer.allocateDirect(80);
private String method(){
buf.flip();
byte[] bytes = byte[10]; //creates a byte array where you can place your data 
buf.get(bytes); //reads data from buffer and places it in the byte array created above
return bytes;
}

写()示例;在将数据从套接字通道读取到缓冲区后,您可能希望将其写回套接字通道 - 假设您想要实现类似服务器的东西,它会回显从客户端接收到的相同消息。

因此,您将从通道读取到缓冲区并从缓冲区读取回通道

SocketChannel socketChannel = SocketChannel.open();
...

ByteBuffer buf = ByteBuffer.allocateDirect(80);

int data = socketChannel.read(buf); // Reads from channel and places it into the buffer
while(data != -1){ //checks if not end of reading
buf.flip();        //prepares for writing
....
socketChannel.write(buf) // if you had initially placed data into buf and you want to read 
                         //from it so that you can write it back into the channel


  }
于 2018-02-02T02:29:00.547 回答