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

Ton*_*ark 12 java bytebuffer initialization

这是:

ByteBuffer buf = ByteBuffer.allocate(1000);
Run Code Online (Sandbox Code Playgroud)

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

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

编辑:更多详情:

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

Ada*_*kin 12

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

If you need to read an unknown amount of data using a ByteBuffer, consider using a loop with your buffer and append the data to a ByteArrayOutputStream as you read it. When you are finished, call toByteArray() to get the final byte array.

Any time when you aren't absolutely sure of the size (or maximum size) of a given input, reading in a loop (possibly using a ByteArrayOutputStream, but otherwise just processing the data as a stream, as it is read) is the only way to handle it. Without some sort of loop, any remaining data will of course be lost.

For example:

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...
}
Run Code Online (Sandbox Code Playgroud)

If you instead wanted to write Java ints, or other things that aren't raw bytes, you can wrap your ByteArrayOutputStream in a DataOutputStream:

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

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

byte[] allBytes = baos.toByteArray();    
Run Code Online (Sandbox Code Playgroud)


Dav*_*vis 7

要看.

图书馆

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

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

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


已知数量

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

未知数量

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

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

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

优化

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

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

  • `StringBuffer`的行为有所不同.如果你试图添加更多,那么`ByteBuffer`会抛出一个`BufferOverflowException`. (4认同)

Jon*_*eet 5

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

您预计会遇到什么问题?