18

这是:

ByteBuffer buf = ByteBuffer.allocate(1000);

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

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

编辑:更多细节:

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

4

3 回答 3

16

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

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

任何时候,当您不确定给定输入的大小(或最大大小)时,循环读取(可能使用 a 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...
}

如果您想编写 Javaint或其他不是原始字节的东西,您可以将您的内容包装ByteArrayOutputStream在 a 中DataOutputStream

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

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

byte[] allBytes = baos.toByteArray();    
于 2009-09-08T20:05:12.117 回答
8

依靠。

图书馆

对于大多数问题域来说,转换文件格式往往是一个已解决的问题。例如:

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

名单很长。第一个问题应该是“哪个图书馆可以完成这项任务?” 如果性能是一个考虑因素,您的时间可能更适合用于优化现有包以满足您的需求,而不是编写另一个工具。(作为奖励,其他人可以从集中式工作中受益。)


已知数量

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

未知数量

当字节数确实未知时,您可以做一些事情:

  • 做一个猜想。
  • 分析示例数据集以缓冲;使用平均长度。

例子

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

优化

不管怎样,这可能是一个过早的优化。通常,当您想减少执行的内部内存重新分配的数量时,您会分配一组字节数。

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

于 2009-09-08T20:05:56.000 回答
5

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

你期待什么问题?

于 2009-09-08T20:04:20.793 回答