DNG/TIFFファイルのリーダ/ライターで作業しています。一般的なファイル(FileInputStream
、FileChannel
、RandomAccessFile
)を扱ういくつかのオプションがあるので、どの戦略が自分のニーズに合っているのだろうかと思っています。画像の(1-3)Javaの複数のファイルから分散データを読み取る
- 一部(5-20)の小ブロック(数十百バイト)
- 非常にいくつかの大きな連続ブロック:
DNG/TIFFファイルは、の組成物であり、全体的なファイルサイズが約15までのMIB(圧縮された14ビットの生データ)の範囲
- いくつかの(多分20-50)非常に小さなブロック(4-16バイト)
(100 MIBへアップ)データ100 MiB(非圧縮フロートデータ)。処理するファイルの数は50〜400です。
2つの使用パターンがあります。
- 読むすべてのファイルのすべてのメタデータ(画像データ以外のすべて)
- 読むには、すべてのファイルからのすべての画像データが私は
現在はFileChannel
を使用し、map()
を実行してファイル全体をカバーするMappedByteBuffer
を取得します。私がメタデータを読むことに興味があれば、これはかなり無駄に思えます。別の問題は、マップされたメモリを解放していることです。パージングなどのためにマップされたバッファのスライスを渡すと、基底のMappedByteBuffer
は収集されません。
今度はFileChannel
の小さなチャンクをいくつかのread()
のメソッドを使用してコピーし、大きな生データ領域のみをマップすることにしました。欠点は何readShort()
はありませんので、単一の値の読み取りが非常に複雑なようだということですなど:
short readShort(long offset) throws IOException, InterruptedException {
return read(offset, Short.BYTES).getShort();
}
ByteBuffer read(long offset, long byteCount) throws IOException, InterruptedException {
ByteBuffer buffer = ByteBuffer.allocate(Math.toIntExact(byteCount));
buffer.order(GenericTiffFileReader.this.byteOrder);
GenericTiffFileReader.this.readInto(buffer, offset);
return buffer;
}
private void readInto(ByteBuffer buffer, long startOffset)
throws IOException, InterruptedException {
long offset = startOffset;
while (buffer.hasRemaining()) {
int bytesRead = this.channel.read(buffer, offset);
switch (bytesRead) {
case 0:
Thread.sleep(10);
break;
case -1:
throw new EOFException("unexpected end of file");
default:
offset += bytesRead;
}
}
buffer.flip();
}
RandomAccessFile
はreadShort()
またはreadFully()
のような便利な方法を提供しますが、リトルエンディアンバイト順を扱うことができません。
したがって、1バイトと巨大ブロックの分散読み取りを処理するための慣用的な方法はありますか? 100ByBのファイル全体をメモリマッピングするだけで、何百バイトもの読み込みや読み込みができますか?
すべての読み取りに1つのByteBufferを使用します。それらを作成するのはかなり高価です。 – EJP
サイズが動的であり、同時使用が禁止されるため、最終アプリケーションでは 'ByteBuffer'を事前に割り当てることはできません。 –