ByteBuffer的flip方法的目的是什么?(为什么称其为“flip”?)

118
ByteBuffer的flip()方法为什么被称为“flip”?这里的“flipped”是什么意思?根据API文档,连续两次翻转不会恢复原始状态,并且多次翻转可能会导致limit()变为零。
我是否可以以某种方式“取消翻转”,以便重用已超出限制的字节?
我是否可以将尾部与其他数据连接起来进行翻转?

6
它会将缓冲区从读模式切换到写模式(反之亦然)。 - Brian Roach
2
@BrianRoach:它可以从读取翻转到写入,但对于从写入翻转到读取来说并不是很有用,除非您正在编写固定大小的结构。对于从写入翻转到读取,请改用“reset”。 - nneonneo
记得提出“客观”的问题;或者至少使主要问题看起来是客观的:D - user166390
@nneonneo - 这有点不是问题,我不会花太多时间解释细节,因此只是一个评论和链接。 - Brian Roach
5个回答

153

ByteBuffer的常见用途之一是逐步构建某些数据结构,然后将整个结构写入磁盘。使用flip从“读I/O”(使用put)翻转到“写I/O”(使用get):在使用put序列填充ByteBuffer后,flip将设置缓冲区的限制为当前位置,并将位置重置为零。这会使得未来从缓冲区getwrite的操作写入所有被put到缓冲区中的内容,而不再多写。

完成put后,您可能希望重用ByteBuffer来构建另一个数据结构。要“取消翻转”,请调用clear。这将重置限制为容量(使整个缓冲区可用),并将位置重置为0。

因此,一个典型的使用场景:

ByteBuffer b = new ByteBuffer(1024);
for(int i=0; i<N; i++) {
    b.clear();
    b.put(header[i]);
    b.put(data[i]);
    b.flip();
    out.write(b);
}

一个可写的字节通道,例如FileChannelSocketChannel - nneonneo
6
任何其他具有write(ByteBuffer)方法的东西。(它的类型并不重要...) - Stephen C
1
它应该使用Buffer.clear来将限制重置为容量并将位置重置为0。Buffer.reset仅将位置重置为“标记”。 - Kelvin Ng
1
@KelvinNg:你说得对,我已经修改了答案以反映这一点。感谢你的指正! - nneonneo
1
@user963241:从 I/O 中读取到缓冲区,从缓冲区写入到 I/O。 - nneonneo
显示剩余5条评论

15

Flip将当前位置的值赋给限制属性,同时将位置属性设置为0。 Flip可用于从缓冲区中仅排除活动元素。

例如,下面的程序打印“hello”而不是缓冲区的空元素。方法调用limitposition可以替换为flip

CharBuffer cbuff = CharBuffer.allocate(40);
cbuff.put("hello"); 
// These two lines below are what flip does
cbuff.limit(cbuff.position());
cbuff.position(0);
    
while(cbuff.hasRemaining()) {
    System.out.println(cbuff.get());
}

请参阅http://www.zoftino.com/java-nio-tutorial了解有关缓冲区和通道的更多信息。


感谢您提供如此详尽的链接!当源被包含在内时,这是非常好的。Java API文档似乎使用“flip”一词而没有解释,好像它是一个常见的计算机科学术语,但显然有些人(包括我)并不这样认为。 - John

3

flip()方法使缓冲区准备好进行新的通道写入或相对获取操作:它将限制设置为当前位置,然后将位置设置为零。

缓冲区跟踪写入其中的数据。在写入后,调用flip()方法以从写入模式切换到读取模式。


1

缓冲区具有固定的 capacity;它维护2个指针:startendget() 返回 start 位置的字节并递增 startput() 将字节放置在 end 位置并递增 end。没有 flip()


7
那么,有哪些抱怨呢?如果你有一些个人不满也可以,但仅仅说“X API很糟糕,人们都这么说”是没有意义的。 - nneonneo
13
发布那个链接就是你一开始要做的全部。我从未指责你撒谎,我只是要求你详细说明投诉的来源和性质。 - nneonneo
9
这也是一个人们不会轻易相信他人的地方,除非说话者的话听起来可信。 - arunmoezhi
8
毫不夸张地说,ByteBuffer 的设计有缺陷,甚至无需提供来源。flip 没有实际用处,只会在忘记翻转时引入错误的源头。如果它们有一种无法控制的冲动要将其放入,至少应该使翻转和未翻转的 ByteBuffer 成为不同的类,这样类型系统就可以捕捉到错误。 - Gurgeh
4
这里没有任何回答问题的内容。 - user207421
显示剩余6条评论

0

compact 是一般使用情况下 flip 的相反操作。

buf = ByteBuffer.allocate(...);  // create
buf.put(...);   // write
buf.flip();     // get ready to read
buf.get(...);   // read some of the data
buf.compact();  // delete the read data and get ready to write again

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接