18

Is this:

ByteBuffer buf = ByteBuffer.allocate(1000);

...the only way to initialize a ByteBuffer?

What if I have no idea how many bytes I need to allocate..?

Edit: More details:

I'm converting one image file format to a TIFF file. The problem is the starting file format can be any size, but I need to write the data in the TIFF to little endian. So I'm reading the stuff I'm eventually going to print to the TIFF file into the ByteBuffer first so I can put everything in Little Endian, then I'm going to write it to the outfile. I guess since I know how long IFDs are, headers are, and I can probably figure out how many bytes in each image plane, I can just use multiple ByteBuffers during this whole process.

4

3 に答える 3

16

使用する場所ByteBufferのタイプは、通常、それ以外の場合はバイト配列 (これも固定サイズ) を使用する場所のタイプです。同期 I/O ではバイト配列を使用することが多く、非同期 I/O では代わりに ByteBuffers が使用されます。

を使用して不明な量のデータを読み取る必要がある場合は、バッファでループを使用し、読み取るときにデータをByteArrayOutputStreamに追加することをByteBuffer検討してください。終了したら、 を呼び出して最終的なバイト配列を取得します。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...
}

int代わりに Javaやその他の raw バイトではないものを書きたい場合は、次のようByteArrayOutputStreamにラップすることができます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は、オフィス スプレッドシート形式間で変換できます。
  • Flexmarkは、Markdown から HTML を生成できます。

リストは長いです。最初の質問は、「このタスクを実行できるライブラリはどれか?」です。パフォーマンスが考慮される場合は、さらに別のツールを作成するよりも、既存のパッケージをニーズに合わせて最適化することに時間を費やす方がよいでしょう。(おまけとして、集中型の作業の恩恵を受けることができます。)


既知の量

  • ファイルを読む?file.size()バイトを割り当てます。
  • 文字列をコピーしますか? string.length()バイトを割り当てます。
  • TCP パケットをコピーしていますか? たとえば、1500 バイトを割り当てます。

不明な数量

バイト数が本当に不明な場合は、いくつかのことを行うことができます。

  • 推測してください。
  • サンプル データ セットを分析してバッファします。平均的な長さを使用します。

Java のStringBufferは、特に指示がない限り、初期バッファ サイズを使用して 16 文字を保持します。16 文字がいっぱいになると、新しい長い配列が割り当てられ、元の 16 文字がコピーされます。の初期サイズが 1024 文字の場合StringBuffer、再割り当てはそれほど早くも頻繁にも発生しません。

最適化

いずれにせよ、これはおそらく時期尚早の最適化です。通常、実行される内部メモリの再割り当ての数を減らしたい場合は、セット数のバイトを割り当てます。

これがアプリケーションのボトルネックになることはほとんどありません。

于 2009-09-08T20:05:56.000 に答える
5

アイデアは、データ全体ではなく、単なるバッファであるということです。これは、チャンクを読み取り、処理する (別の場所に書き込む可能性がある) データの一時的な休憩場所です。したがって、十分な大きさの「チャンク」を割り当てれば、通常は問題になりません。

どのような問題が予想されますか?

于 2009-09-08T20:04:20.793 に答える