【问题标题】:Java NIO ByteBuffer, write after flipJava NIO ByteBuffer,翻转后写入
【发布时间】:2018-01-25 23:38:25
【问题描述】:

我是 Java ByteBuffers 的新手,想知道在翻转后写入 ByteBuffer 的正确方法是什么。

在我的用例中,我正在将 outputBuffer 写入套接字:

    outBuffer.flip();
    //Non-blocking SocketChannel
    int bytesWritten = getSocket().write(outBuffer);

在此之后,必须再次写入输出缓冲区。此外,并非 outBuffer 中的所有字节都已写入套接字。

既然它目前是翻转的,我怎样才能让它再次可写,如果它仍然在缓冲区中并且没有被写入套接字,我怎样才能让它再次可写,而不覆盖任何数据?

如果我是对的,outBuffer.position() == bytesWritten 和 limit 应该是要写入的数据量。

那么使用以下内容来重用输出缓冲区是否正确? :

   int limit = outBuffer.limit()  
   outBuffer.limit(outBuffer.capacity());
   outBuffer.position(limit);

【问题讨论】:

  • 是否要在重用之前写入(翻转的)缓冲区的全部内容?
  • 这是个好问题。我认为getSocket().write() 会在当前时间尽可能多地写入,并且不知道是否值得轮询以写入整个缓冲区。对于这个例子,我只是在套接字允许的范围内写入(bytesWritten),然后想在此之后继续放入缓冲区,而不覆盖任何未写入套接字的数据。

标签: java byte buffer nio


【解决方案1】:

再次来自 API 规范: 以下循环通过缓冲区 buf 将字节从一个通道复制到另一个通道:

while (in.read(buf) >= 0 || buf.position != 0) {
   buf.flip();
   out.write(buf);
   buf.compact();    // In case of partial write
}

【讨论】:

  • 所以使用compact?生病看看那个谢谢!这是一个常见的问题还是什么?我在谷歌上找不到任何东西!
  • AFAIU 这是正确的方法 - 但是,如果它不起作用,请告诉我。
  • 这是正确的方法。请注意,它适用于在读取到达流末尾后仍有数据要写入的情况:换句话说,如果存在短写入,则使用compact() 和双重条件。另请注意,循环实际上仅适用于阻塞模式。在非阻塞模式下,您只会在有 OP_READ 事件时读取。
  • 这很好,我想我不知道compact(),我总是手动完成这一步。
【解决方案2】:

因为它现在被翻转了

它将保持翻转状态。写入不会改变这一点。

如果它仍在缓冲区中并且没有写入套接字,我怎样才能让它再次可写,而不覆盖任何数据?

您无需执行任何操作,但如果您想在再次写入之前先阅读,您应该执行翻转/写入/压缩。如果您只想重复写入,只需再次调用write(),缓冲区仍处于当前状态。

但我更喜欢始终保持这些缓冲区为读取做好准备,因此不会出现滑倒的可能性,并且当那些操作是必要的,可以说是原子的。

请注意,您应该不要使用clear(),除非您确定写入已完成且缓冲区现在为空。在那种情况下,compact 和 clear 是等价的。但总是紧凑更简单。

如果您在阻塞模式下复制,请使用@zlakad 引用的循环。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多