Java中未知长度的字节数组:第二部分

时间:2011-06-26 00:35:32

标签: java arrays dynamic byte

"Byte array of unknown length in java"类似,我需要能够将数据源中未知数量的字节写入byte []数组。 然而我需要能够从先前存储的字节读取压缩算法,因此ByteArrayOutputStream对我不起作用。

现在我有一个方案,我分配固定大小N的ByteBuffers,添加一个新的,当我达到N,2N,3N字节等。数据耗尽后我将所有缓冲区转储到一个现在已知大小的数组

有更好的方法吗?固定大小的缓冲区降低了压缩算法的灵活性。

6 个答案:

答案 0 :(得分:5)

使用循环字节缓冲区怎么样?它有可能动态增长并且效率很高。

这里有一个实现:http://ostermiller.org/utils/CircularByteBuffer.java.html

答案 1 :(得分:4)

为什么不将ByteArrayOutputStream作为子类?这样,您的子类可以访问受保护的bufcount字段,您可以向类添加方法以直接操作它们。

答案 2 :(得分:2)

ByteArrayOutputStream的费用是调整底层数组的大小。你的固定块程序消除了很多。如果调整大小对你来说不够昂贵(例如在测试中ByteArrayOutputStream“足够快”,并且不提供撤消内存压力),那么根据vanza建议的子类化ByteArrayOutputStream可能对你有用。

我不知道你的压缩算法,所以我不能说为什么你的块列表使它不那么灵活,甚至为什么压缩算法甚至不知道块。但由于块可以通过动态,您可以适当调整块大小,以更好地支持您正在使用的各种压缩算法。

如果压缩算法可以在“流”上工作(即固定大小的数据块),则块大小应该很重要,因为您可以隐藏实现中的所有这些细节。完美的世界是,如果压缩算法希望其数据块与您分配的块的大小相匹配,那么您就不必复制数据来为压缩器提供数据。

答案 3 :(得分:2)

虽然你当然可以使用ArrayList,你几乎可以看到4-8倍的内存开销 - 假设字节不是新分配但是共享一个全局实例(因为这对于整数是真的,我认为它有效对于字节也是如此) - 并且你丢失了所有缓存局部性。

因此,虽然您可以将ByteArrayOutputStream子类化,但即使在那里您也不需要开销(方法已同步)。所以我个人会推出自己的类,当你写它时它会动态增长。效率低于您当前的方法,但很简单,我们都知道具有摊销成本的部分 - 否则您显然也可以使用您的解决方案。只要您将解决方案包装在一个干净的界面中,您就会隐藏复杂性并仍能获得良好的性能

或以其他方式说:不,你几乎不能比你已经做的更有效率,并且每个内置的java Collection都应该因为某种原因而表现更差。

答案 4 :(得分:2)

克里斯回答说CircularByteBuffer api是要走的路。幸运的是,它现在在中央maven repo。引用this link的摘录,简单如下:

循环缓冲区的单线程示例

// buffer all data in a circular buffer of infinite size
CircularByteBuffer cbb = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);
class1.putDataOnOutputStream(cbb.getOutputStream());
class2.processDataFromInputStream(cbb.getInputStream());

优点是:

  • 一个CircularBuffer类而不是两个管道类。
  • 在“缓冲所有数据”和“额外线程”方法之间进行转换更容易。
  • 您可以更改缓冲区大小,而不是依赖于管道中硬编码的1k缓冲区。

最后,我们没有内存问题和管道API

答案 5 :(得分:0)

为简单起见,您可以考虑使用java.util.ArrayList

ArrayList<Byte> a = new ArrayList<Byte>();
a.add(value1);
a.add(value2);
...
byte value = a.get(0);

Java 1.5及更高版本将在byteByte类型之间提供自动装箱和拆箱功能。性能可能略微ByteArrayOutputStream更差,但它易于阅读和理解。