【问题标题】:What is the purpose of ByteBuffer's flip method? (And why is it called "flip"?)ByteBuffer翻转方法的目的是什么? (为什么叫“翻转”?)
【发布时间】:2013-01-25 10:09:05
【问题描述】:

为什么ByteBuffer的flip()方法叫“flip”?这里“翻转”了什么?根据 apidoc,连续两次翻转不会恢复原始状态,多次翻转可能会使limit() 变为零。

我可以以某种方式“取消翻转”以重用超出限制的字节吗?

我可以将尾部与其他一些数据连接起来吗?

【问题讨论】:

  • 它将缓冲区从读“翻转”到写(反之亦然)。 thushw.blogspot.com/2009/10/…
  • @BrianRoach:它从读到写翻转,但对于写到读来说没有那么有用,除非你正在编写固定大小的结构。对于从写入到读取的翻转,请改用reset
  • 记得问“客观”的问题;或者,至少,让主要问题看起来很客观:D
  • @nneonneo - 这不是问题,不会花太多时间解释细节,因此只是评论和链接。

标签: java flip bytebuffer


【解决方案1】:

ByteBuffer 的一个相当常见的用例是逐个构建一些数据结构,然后将整个结构写入磁盘。 flip 用于将ByteBuffer 从“从 I/O 读取”(putting) 翻转为“写入 I/O”(getting):在使用了一系列 puts 之后要填充ByteBufferflip 会将缓冲区的限制设置为当前位置并将位置重置为零。这具有使缓冲区中的未来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);
}

【讨论】:

  • 一个WritableByteChannel,如FileChannelSocketChannel
  • 或其他任何具有write(ByteBuffer) 方法的东西。 (它的类型是什么并不真正相关......)
  • 它应该Buffer.clear将容量和位置的限制重置为0。Buffer.reset仅将位置重置为mark
  • @KelvinNg:你是对的;我已经修改了答案以反映这一点。谢谢你的好收获!
  • @user963241: 将 from I/O 读入缓冲区,将 from 缓冲区写入 I/O。
【解决方案2】:

Flip 将当前位置值分配给 limit 属性并将 position 属性设置为 0。Flip 仅用于从缓冲区中排出活动元素。

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

CharBuffer cbuff = CharBuffer.allocate(40);
cbuff.put("hello"); 
// what below two line of code is 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 文档似乎不加解释地使用了“翻转”这个词,就好像它是一个常见的计算机科学术语,但显然有几个人(包括我)没有发现这种情况。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    ByteBuffer 设计不当。有很多来自体面的程序员的抱怨。

    所以不要试图去推理它,只要仔细研究和使用 API。

    现在我不能在不提出替代方案的情况下说坏话,所以这里是:

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

    【讨论】:

    • 那么,有什么抱怨?如果您有一些个人不满也可以,但仅仅说“X API 很烂,人们这么说”是不行的。
    • 发布该链接实际上是您首先要做的所有事情。我从来没有指责你撒谎,我只是要求你详细说明投诉的来源和性质。
    • 这也是一个除非听起来可信,否则人们不会相信某人的话的地方。
    • 你甚至不需要提供来源。很明显 ByteBuffer 设计不当。翻转并没有达到目的,它只是在您忘记翻转时引入了错误来源。如果他们有一种无法控制的冲动将其放入,至少将翻转和未翻转的 ByteBuffers 设置为不同的类,这样类型系统才能捕捉到错误。
    • 这里没有什么可以回答这个问题。
    猜你喜欢
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 2013-09-07
    • 2016-04-23
    • 2013-12-28
    • 2019-01-14
    相关资源
    最近更新 更多