如果你不知道预先分配了多少字节,如何初始化ByteBuffer?

时间:2009-09-08 19:59:31

标签: java initialization bytebuffer

这是:

ByteBuffer buf = ByteBuffer.allocate(1000);

...初始化ByteBuffer的唯一方法?

如果我不知道需要分配多少字节怎么办?

修改:更多详情:

我正在将一种图像文件格式转换为TIFF文件。问题是起始文件格式可以是任何大小,但我需要将TIFF中的数据写入小端。所以我正在阅读我最终将打印到TIFF文件的内容首先打印到ByteBuffer中,这样我就可以将所有内容放入Little Endian中,然后我将其写入outfile。我想因为我知道IFD有多长,标题是,我可以计算出每个图像平面中有多少字节,我可以在整个过程中使用多个ByteBuffers。

3 个答案:

答案 0 :(得分:11)

您将使用ByteBuffer的地方类型通常是您将使用字节数组(也具有固定大小)的地方类型。对于同步I / O,您经常使用字节数组,使用异步I / O,而是使用ByteBuffers。

如果您需要使用ByteBuffer读取未知数量的数据,请考虑在缓冲区中使用循环,并在阅读时将数据附加到ByteArrayOutputStream 。完成后,调用toByteArray()以获取最终的字节数组。

任何时候当你不完全确定给定输入的大小(或最大大小)时,读取循环(可能使用ByteArrayOutputStream,但只是将数据作为流处理,如它是读取)是处理它的唯一方法。如果没有某种循环,任何剩余的数据当然都会丢失。

例如:

final byte[] buf = new byte[4096];
int numRead;

// Use try-with-resources to auto-close streams.
try(
  final FileInputStream fis = new FileInputStream(...);
  final ByteArrayOutputStream baos = new ByteArrayOutputStream()
) {
  while ((numRead = fis.read(buf)) > 0) {
    baos.write(buf, 0, numRead);
  }

  final byte[] allBytes = baos.toByteArray();

  // Do something with the data.
}
catch( final Exception e ) {
  // Do something on failure...
}

如果你想编写Java int或其他不是原始字节的东西,你可以将ByteArrayOutputStream包裹在DataOutputStream中:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);

while (thereAreMoreIntsFromSomewhere()) {
    int someInt = getIntFromSomewhere();
    dos.writeInt(someInt);
}

byte[] allBytes = baos.toByteArray();    

答案 1 :(得分:7)

取决于

转换文件格式往往是大多数问题域的解决问题。例如:

  • Batik可以在各种图片格式(包括TIFF)之间进行转码。
  • Apache POI可以在办公室电子表格格式之间进行转换。
  • Flexmark可以从Markdown生成HTML。

列表很长。第一个问题应该是,“library可以完成这项任务?”如果考虑性能,那么与编写其他工具相比,优化现有软件包以满足您的需求可能会花费更多时间。 (作为奖励,其他人可以从集中工作中受益。)


已知数量

  • 读取文件?分配file.size()个字节。
  • 复制一个字符串?分配string.length()个字节。
  • 复制TCP数据包?例如,分配1500个字节。

未知数量

当字节数真的未知时,你可以做一些事情:

  • 猜猜。
  • 分析要缓冲的示例数据集;使用平均长度。

实施例

除非另有说明,否则Java StringBuffer使用初始缓冲区大小来保存16个字符。填充16个字符后,将分配一个新的较长的数组,然后复制原始的16个字符。如果StringBuffer的初始大小为1024个字符,则重新分配不会像早期或经常那样发生。

优化

无论哪种方式,这可能是一个不成熟的优化。通常,当您想减少执行的内部内存重新分配的数量时,您将分配一定数量的字节。

这不太可能是应用程序的瓶颈。

答案 2 :(得分:4)

这个想法是它只是一个缓冲区 - 而不是整个数据。当你读取一个块,处理它(可能在其他地方写它)时,它是数据的临时休息点。所以,给自己分配一个足够大的“块”,通常不会有问题。

您期待什么问题?