Самый быстрый способ чтения относительно больших байтовых файлов в Java - PullRequest
13 голосов
/ 01 февраля 2012

Каков, пожалуй, самый быстрый способ чтения относительно больших файлов с помощью методов ввода-вывода Java? Мое текущее решение использует BufferedInputStream сохранение в байтовом массиве с выделенными ему 1024 байтами. Каждый буфер сохраняется в ArrayList для последующего использования. Весь процесс вызывается через отдельный поток (callable-interface).

Не очень быстро, хотя.

    ArrayList<byte[]> outputArr = new ArrayList<byte[]>();      
    try {
        BufferedInputStream reader = new BufferedInputStream(new FileInputStream (dir+filename));

        byte[] buffer = new byte[LIMIT]; // == 1024 
            int i = 0;
            while (reader.available() != 0) {
                reader.read(buffer);
                i++;
                if (i <= LIMIT){
                    outputArr.add(buffer);
                    i = 0;
                    buffer = null;
                    buffer = new byte[LIMIT];
                }
                else continue;              
            }

         System.out.println("FileReader-Elements: "+outputArr.size()+" w. "+buffer.length+" byte each.");   

Ответы [ 3 ]

39 голосов
/ 01 февраля 2012

Я бы использовал файл с отображением памяти, который достаточно быстр, чтобы сделать в том же потоке.

final FileChannel channel = new FileInputStream(fileName).getChannel();
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

// when finished
channel.close();

Предполагается, что размер файла меньше 2 ГБ и займет 10 миллисекунд или менее.

3 голосов
/ 01 февраля 2012

Не используйте available(): это ненадежно. И не игнорируйте результат метода read(): он говорит вам, сколько байтов действительно было прочитано. И если вы хотите прочитать все в памяти, используйте ByteArrayOutputStream, а не List<byte[]>:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
int read;
while ((read = reader.read(buffer)) >= 0) {
    baos.write(buffer, 0, read);
}
byte[] everything = baos.toByteArray();

Я думаю, что 1024 немного меньше размера буфера. Я бы использовал больший буфер (что-то вроде 16 КБ или 32 КБ)

Обратите внимание, что Apache Commons IO и Guava имеют служебные методы, которые делают это для вас, и уже оптимизированы.

1 голос
/ 01 февраля 2012

Посмотрите на API Java NIO (неблокирующий ввод / вывод).Кроме того, этот вопрос может оказаться полезным.

У меня нет большого опыта работы с IO, но я слышал, что NIO - гораздо более эффективный способобработка больших наборов данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...