是否有一个Java ByteBuffer实现,在其底层将多个支持ByteBuffer组合起来使用?

8
我有一个或多个包含单个消息部分的ByteBuffer。现在我想要读取这条消息,但我不想将N个ByteBuffer复制成一个。我的解析器期望有一份完整消息的单个ByteBuffer,但我的消息被分成了N个ByteBuffer。
有没有办法将这些N个ByteBuffer组合成一个而无需复制字节?我想象中可能会有某种智能实现ByteBuffer抽象类,它由这些ByteBuffer支持,并且只需调整指针和委托以正确地指向ByteBuffer。
如果你好奇我为什么需要这个,请查看来自BM&F/Bovespa的协议。他们将一条消息分成块,并且这些块可以以不同的数据包乱序传输,换句话说,相同的消息顺序可能会出现在多个数据包中,每个数据包都有一个消息块。我无法按顺序将相同的ByteBuffer写入,因为这些块可能是无序的。:(
我是否遗漏了更聪明的方法?看起来,考虑到下面的块协议,没有办法按顺序将相同的ByteBuffer写入。 :( enter image description here enter image description here

1
如果您不想将它们全部合并到单个缓冲区中,那么为什么您的解析器要求一个单独的ByteBuffer呢?听起来像是代码架构问题。 - jlewkovich
@JL 你可能是对的,但我不这么认为。请检查我的编辑,以包括我正在尝试实现的协议。 - Michelle Queen
他们肯定提供Java API吧?你不应该自己做这些。其他来源肯定有Java的FIX API可用。 - user207421
好的,我不知道你为什么认为没有办法按顺序向ByteBuffer写入数据。这正是所有无索引的put()方法所做的。你甚至可以在单个操作中将一个ByteBuffer的全部内容完全放入另一个ByteBuffer中。 - user207421
@EJP,您可能没有阅读上面的协议规范。假设消息3231有4个部分。它们以UDP数据包的形式无序到达,例如0、2、3、1。我不能将它们写入同一个ByteBuffer中。我必须以某种方式按正确顺序重新组装所有块。我认为解决方案在我打字时突然浮现,但我想等待其他人对此的看法。 - Michelle Queen
显示剩余4条评论
2个回答

0

我认为你正在寻找的数据结构被称为(据我所知)链式缓冲区。在内部,它是一个动态增长的集合(例如Java中的ArrayList)由字节数组或缓冲区组成,而在外部,该结构就像一个常规的Buffer

如果你处理性能问题,它可能非常方便,尽管一些操作的实现可能并不完全简单(例如查找给定模式的位置)。

我所知道的唯一公共Java实现是NCHOVY的ChainBufferKraken中(虽然已经不再维护)。


-4
您可以将ByteBuffer链接在一起,返回一个ByteBuffer,如下所示:
bba.append(bbb.toBytes()).append(bbc.toBytes())

这将导致一个单独的 ByteBuffer,可以传递给你的解析方法。

它实际上创建了一个副本,但是除非你将其分配给某个对象,否则它将被排队等待被垃圾回收。

如果你不知道 ByteBuffer 的数量,可以使用一个 ByteBuffer 的列表,并在运行时将每个 ByteBuffer 添加进去,然后再在循环中将它们连接起来。你可以在连接之前对列表进行排序,以便按照你希望的顺序显示这些块。


我在ByteBuffer的javadoc中找不到这个append方法。你是指put方法吗?即使它存在,看起来它只是将字节复制到一个新的ByteBuffer中,对吧?将N个ByteBuffer的所有数据复制到一个新的ByteBuffer中是微不足道且昂贵的解决方案。你同意吗? - Michelle Queen
http://download.oracle.com/otn_hosted_doc/jdeveloper/1012/jdev-doc/oracle/ide/util/ByteBuffer.html - CharlieS
有些人会点踩以凸显自己的评论更重要。这不是我的问题,我也不在意 :) - CharlieS
复制数据很简单,但成本涉及到许多方面。我更喜欢易于维护的代码而不是高效的代码。效率可以通过廉价资源解决。糟糕的代码维护起来很昂贵。显然需要平衡。 :) - CharlieS
2
这个downvote可能是因为它指的是oracle.ide.util.ByteBuffer,而不是java.nio.ByteBuffer... - Marco13

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