Подтвердить что ты не робот

Buffered RandomAccessFile java

RandomAccessFile довольно медленный для случайного доступа к файлу. Вы часто читаете о внедрении над ним буферизованного слоя, но код, делающий это, невозможно найти в Интернете.

Итак, мой вопрос: вы, ребята, знаете какую-либо реализацию с открытым исходным кодом этого класса, поделитесь указателем или поделитесь своей собственной реализацией?

Было бы неплохо, если бы этот вопрос получился как набор полезных ссылок и кода об этой проблеме, которые, я уверен, разделяют многие и никогда не исправляются должным образом SUN.

Пожалуйста, не ссылайтесь на MemoryMapping, поскольку файлы могут быть больше, чем Integer.MAX_VALUE.

4b9b3361

Ответ 1

Ну, я не вижу причины не использовать java.nio.MappedByteBuffer, даже если файлы больше Integer.MAX_VALUE.

Очевидно, вам не удастся определить один MappedByteBuffer для всего файла. Но у вас может быть несколько MappedByteBuffers, обращающихся к различным регионам файла.

Определение позиции и размера в FileChannenel.map имеет тип long, что означает, что вы можете предоставлять значения по Integer.MAX_VALUE, единственное, что вам нужно позаботиться, это размер вашего буфера не будет больше Integer.MAX_VALUE.

Следовательно, вы можете определить несколько таких карт:

buffer[0] = fileChannel.map(FileChannel.MapMode.READ_WRITE,0,2147483647L);
buffer[1] = fileChannel.map(FileChannel.MapMode.READ_WRITE,2147483647L, Integer.MAX_VALUE);
buffer[2] = fileChannel.map(FileChannel.MapMode.READ_WRITE, 4294967294L, Integer.MAX_VALUE);
...

В итоге размер не может быть больше Integer.MAX_VALUE, но стартовая позиция может быть в любом месте вашего файла.

В книге Java NIO автор Рон Хитченс заявляет:

Доступ к файлу через механизм отображения памяти может быть далеко более эффективны, чем чтение или запись данных обычными средствами, даже если используя каналы. Нет явной системы должны быть сделаны вызовы, которые могут быть кропотливый. Что еще более важно, виртуальная память система автоматически кэширует память страницы. Эти страницы будут кэшироваться используя системную память, и не будет потреблять пространство из памяти JVM куча.

Как только страница памяти была сделана действительной (введенный с диска), это может быть снова доступ к полной аппаратной скорости без необходимости делать другой системный вызов для получения данных. Большой, структурированные файлы, содержащие индексы или другие разделы, на которые ссылаются или часто обновляется исключительно из памяти. когда в сочетании с блокировкой файлов для защиты критические разделы и контроль транзакционной атомарности, вы начинаете см., как буферы с отображением памяти могут быть положительно использовать.

Я действительно сомневаюсь, что вы найдете сторонний API, который сделает что-то лучше этого. Возможно, вы можете найти API, написанный поверх этой архитектуры, чтобы упростить работу.

Вы не думаете, что этот подход должен работать для вас?

Ответ 2

Вы можете создать BufferedInputStream из RandomAccessFile с кодом, например,

 RandomAccessFile raf = ...
 FileInputStream fis = new FileInputStream(raf.getFD());
 BufferedInputStream bis = new BufferedInputStream(fis);

Некоторые примечания

  • Закрытие FileInputStream закроет RandomAccessFile и наоборот
  • RandomAccessFile и FileInputStream указывают на ту же позицию, поэтому чтение из FileInputStream будет продвигать указатель файла для RandomAccessFile и наоборот

Вероятно, способ, которым вы хотите использовать это, будет чем-то вроде

RandomAccessFile raf = ...
FileInputStream fis = new FileInputStream(raf.getFD());
BufferedInputStream bis = new BufferedInputStream(fis);

//do some reads with buffer
bis.read(...);
bis.read(...);

//seek to a a different section of the file, so discard the previous buffer
raf.seek(...);
bis = new BufferedInputStream(fis);
bis.read(...);
bis.read(...);

Ответ 3

RandomAccessFile довольно медленный для случайного доступа к файлу. Вы часто читаете о внедрении над ним буферизованного слоя, но код, делающий это, невозможно найти в Интернете.

Ну, можно найти онлайн.
Во-первых, исходный код JAI в jpeg2000 имеет реализацию, а также еще более необремененный имп: http://www.unidata.ucar.edu/software/netcdf-java/

Javadocs:

http://www.unidata.ucar.edu/software/thredds/v4.3/netcdf-java/v4.0/javadoc/ucar/unidata/io/RandomAccessFile.html

Ответ 4

Если вы работаете на 64-битной машине, то файлы с отображением памяти - ваш лучший подход. Просто сопоставьте весь файл с массивом буферов равного размера, затем выберите буфер для каждой записи по мере необходимости (т.е. Ответ edalorzo, однако вы хотите перекрывать буферы, чтобы у вас не было записей, охватывающих границы).

Если вы работаете на 32-битной JVM, вы застряли с RandomAccessFile. Однако вы можете использовать его для чтения byte[], который содержит всю вашу запись, а затем используйте ByteBuffer для извлечения отдельных значений из этого массива. В худшем случае вам необходимо сделать два доступа к файлам: один для получения позиции/размера записи и один для извлечения самой записи.

Однако имейте в виду, что вы можете начать подчеркивать сборщик мусора, если вы создадите много byte[] s, и вы останетесь IO-bound, если вы откажетесь по всему файлу.