Отображаемые в память файлы в Java - PullRequest
8 голосов
/ 21 июня 2009

Я пытался написать очень быстрый Java-код, который должен выполнять много операций ввода-вывода. Я использую файл отображения памяти, который возвращает ByteBuffer:

public static ByteBuffer byteBufferForFile(String fname){
    FileChannel vectorChannel;
    ByteBuffer vector;
    try {
        vectorChannel = new FileInputStream(fname).getChannel();
    } catch (FileNotFoundException e1) {
        e1.printStackTrace();
        return null;
    }
    try {
        vector = vectorChannel.map(MapMode.READ_ONLY,0,vectorChannel.size());
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
    return vector;
}

Проблема, с которой я столкнулся, заключается в том, что метод ByarBuffer .array () (который должен возвращать массив byte []) не работает для файлов только для чтения. Я хочу написать свой код так, чтобы он работал как с буферами памяти, созданными в памяти, так и с буферами, считываемыми с диска. Но я не хочу оборачивать все мои буферы функцией ByteBuffer.wrap (), потому что я боюсь, что это замедлит процесс. Итак, я написал две версии всего: одна для байта [], другая для байтового буфера.

Должен ли я просто обернуть все? Или мне все дважды написать?

Ответы [ 4 ]

10 голосов
/ 16 июля 2009

Кто-нибудь проверял, действительно ли ByteBuffers создан поддержкой отображения памяти, в первую очередь вызывая .array(), независимо от readonly / readwrite?

Насколько я могу судить, из моего возни, ответ: НЕТ . Способность ByteBuffer возвращать прямой массив byte[] через ByteBuffer.array() определяется наличием ByteBuffer.hb (byte[]), которое всегда устанавливается в ноль при создании MappedByteBuffer.

Что для меня отстойно, потому что я надеялся сделать что-то похожее на то, что хотел сделать автор вопроса.

5 голосов
/ 21 июня 2009

Всегда хорошо не изобретать колеса. Apache предоставил прекрасную библиотеку для выполнения операций ввода-вывода. Взгляните на http://commons.apache.org/io/description.html

Вот сценарий, которому он служит. Предположим, у вас есть некоторые данные, которые вы предпочитаю хранить в памяти, но заранее не знаешь, сколько данных там будет. Если их слишком много, вы хотите записать их на диск вместо загрузки памяти, но вы не хотите записывать на диск, пока вы необходимо, потому что диск медленный и является ресурсом, который требует отслеживания для очистки.

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

Вот что DeferredOutputStream делает для вас. Он прячет всю грязь вокруг в точке переключения. Все, что вам нужно сделать, это создать отложите поток в первую очередь, настройте порог, а потом просто напишите в свое удовольствие.

РЕДАКТИРОВАТЬ: я только что сделал небольшой повторный поиск с помощью Google и нашел эту ссылку: http://lists.apple.com/archives/java-dev/2004/Apr/msg00086.html (Молниеносное чтение / запись файла). Очень впечатляет.

4 голосов
/ 21 июня 2009

Обертывание байта [] не замедлит работу ... не будет копий огромных массивов или других небольших недостатков производительности. Из JavaDocs: java.nio.ByteBuffer .wrap ()

Оборачивает байтовый массив в буфер.

Новый буфер будет поддерживаться данным байтовым массивом; , то есть изменения в буфере вызовут массив, который будет изменен и порок наоборот. Емкость нового буфера и предел будет array.length, его позиция будет нулевая, а ее отметка будет неопределенным Его резервный массив будет данный массив, и его массив смещение будет равно нулю.

1 голос
/ 21 июня 2009

Использование функциональности ByteBuffer.wrap () не накладывает больших затрат. Он выделяет простой объект и инициализирует несколько целых чисел. Таким образом, написание алгоритма для ByteBuffer - ваш лучший выбор, если вам нужно работать с файлами только для чтения.

...