清空 ByteBuffer

10
非常简单的问题:我正在从一个SocketChannel读取数据,并希望将结果写入另一个SocketChannel。我使用了一个Selector对象,所以我等待直到一个SocketChannel可读,将数据转储到ByteBuffer中,然后当下一个SocketChannel可写时,将ByteBuffer转储到那里。到目前为止都还好。然而,似乎没有任何方法可以实际“清除”一个ByteBuffer,因此我无法进行任何检查以知道是否有新数据到达。
我尝试了.clear()方法,但显然这并没有清除缓冲区,而只是将缓冲区位置重置为1。
以下是一些示例代码:
ByteBuffer channel1buf = ByteBuffer.allocate(1024);
ByteBuffer channel2buf = ByteBuffer.allocate(1024);

if (key.isReadable()) {
    if (key.channel().equals(channel1)) {
        channel1.read(channel2buf);
    } else if (key.channel().equals(channel2)) {
        channel2.read(channel1buf);
    }
} else if (key.isWritable()) {
    if (key.channel().equals(channel1) && channel1buf.asCharBuffer().length() > 0) {
        channel1.write(channel1buf);
        /* some way to clear channel1buf */
    } else /* same idea for channel2... */
}

在向选择器注册通道时(register方法的第三个参数),应将ByteBuffer用作附件,这样您就可以从SelectionKey中检索附件并避免所有嵌套的if子句。 - mike
3个回答

8

Buffer.clear 方法会重置位置,是的。然后你可以使用 getPosition() > 0 来检查缓冲区之后是否有添加任何内容,不是吗?


那个 几乎 行得通,但缓冲区仍然有旧数据,所以它会打印任何溢出。我想我可以手动遍历缓冲区并清除它,但这似乎不太优雅。 - user1241397
问题是,你为什么在意缓冲区仍然有旧数据呢?清除它并不会让你回收任何东西。只要不查看 getPosition() 以下的任何内容,你就应该没问题了……或者我漏掉了什么吗? - Louis Wasserman
嗯,缓冲区是固定大小的,所以如果我这样做,最终会在缓冲区中用尽空间。 - user1241397
1
不是这样的。当你调用 Buffer.clear() 时,它会将写入位置重置为0,因此对缓冲区的任何新写入都将覆盖清除的旧数据。 - Louis Wasserman
啊,我懂了!不确定“below”指的是什么方向 :-)。 - user1241397
显示剩余3条评论

6

我用这段代码解决了一个相同的问题,希望它能帮到你。

channel1buf.clear();
//zerolize buff manually
channel1buf.put(new byte[1024]);
channel1buf.clear();

1
但是,如果您按照ByteBuffer类的预期使用它(在读取之前调用flip()、在重新读取之前调用rewind()、在写入之前调用clear()compact()),则不需要对缓冲区使用此类ZeroMemory() - Lumi

2

在我看来,分配新的内存(new memory(channel1buf.put(new byte[1024]);))并不是一个更好的解决方案。

您可以使用以下代码段:

java.util.Arrays.fill(channel1buff.array(), (byte)0);

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