我正在研究DNG/TIFF文件的讀寫器。由於有幾個選項可用於處理文件(FileInputStream
,FileChannel
,RandomAccessFile
),我想知道哪種策略適合我的需求。從java中的多個文件讀取零散數據
甲DNG/TIFF文件是一個組合物:
- 一些(5-20)小塊(幾十到幾百個字節)
- 很少(1-3)大的連續圖像的塊數據(高達100 MIB)
- 幾個(或許20-50)非常小的塊(4-16字節)
的整個文件的大小從15 MIB(壓縮14位原始數據)的範圍內至多約100 MiB(未壓縮的浮點數據)。要處理的文件數是50-400。
有兩種使用模式:
- 閱讀所有文件中的所有元數據(以外的所有圖像數據)
- 從所有文件中讀取所有的圖像數據
我目前使用FileChannel
並執行map()
以獲得覆蓋整個文件的MappedByteBuffer
。如果我只是對閱讀元數據感興趣,這看起來很浪費。另一個問題是釋放映射的內存:當我傳遞映射緩衝區的片段進行解析時,將不會收集底層的MappedByteBuffer
。
我現在決定使用幾個read()
-方法複製較小的塊FileChannel
,並且只映射大的原始數據區域。不足之處是讀取一個價值似乎非常複雜,因爲沒有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()
有用的方法,但不能處理小尾數字節順序。
那麼,有沒有一種慣用的方式來處理單個字節和巨塊的分散讀取?內存映射整個100 MiB文件只讀幾百字節浪費或緩慢?
對所有讀取使用一個「ByteBuffer」。創建它們相當昂貴。 – EJP
預分配'ByteBuffer'在最終的應用程序中是不可能的,因爲大小將是動態的,並且會禁止併發使用。 –