Более быстрый способ чтения файла - PullRequest
9 голосов
/ 02 мая 2011

Я работаю над программой, которая имеет около 400 входных файлов и около 40 выходных файлов.Все просто: он читает каждый входной файл и генерирует новый файл с гораздо большим размером (на основе алгоритма).

Я использую метод read () из BufferedReader:

String encoding ="ISO-8859-1";
FileInputStream fis = new FileInputStream(nextFile);
BufferedReader reader = new BufferedReader(new InputStreamReader(fis, encoding));
char[] buffer = new char[8192] ;

Чтобы прочитать входные файлы, я использую это:

private String getNextBlock() throws IOException{
    boolean isNewFile = false;

    int n = reader.read(buffer, 0, buffer.length);
    if(n == -1) {
        return null;
    } else {
        return new String(buffer,0,n);
    }
}

С каждым блоком я делаю некоторые проверки (например, просматривая некоторую строку внутри блока), а затем записываю это в файл:

BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
        new FileOutputStream("fileName"), encoding));

writer.write(textToWrite);

Проблема в том, что это занимает около 12 минут.Я пытаюсь найти что-то еще намного быстрее.Кто-нибудь есть идеи о чем-то лучше?

Спасибо.

Ответы [ 3 ]

20 голосов
/ 02 мая 2011

Вы сможете найти ответ здесь:

http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly

Для лучшей производительности чтения Java нужно помнить четыре вещи:

  • Минимизируйте операции ввода-вывода, читая массив за раз, а не байт за раз. Массив 8 Кбайт - это хороший размер.

  • Минимизируйте вызовы методов, получая данные за один раз, а не за один байт. Используйте индексирование массива, чтобы получить байты в массиве.

  • Минимизируйте блокировки синхронизации потоков, если вам не нужна безопасность потоков. Либо выполняйте меньше вызовов методов для поточно-безопасного класса, либо используйте не поточно-безопасный класс, например FileChannel и MappedByteBuffer.

  • Минимизируйте копирование данных между JVM / OS, внутренними буферами и массивами приложений. Используйте FileChannel с отображением памяти или прямой или упакованный массив ByteBuffer.

4 голосов
/ 02 мая 2011

Поскольку вы не даете слишком много подробностей, я могу предложить вам использовать файлы с отображением в памяти:

FileInputStream f = new FileInputStream(fileName);
FileChannel ch = f.getChannel( );
MappedByteBuffer mbb = ch.map( ch.MapMode.READ_ONLY, 0L, ch.size( ) );
while ( mbb.hasRemaining( ) )  {
      // Access the data using the mbb
}

Это можно сделать, если вы дадите более подробную информацию о том, какие данные хранятся в ваших файлах.

EDIT

Где // доступ к дате с использованием mbb, вы холодным образом декодируете свой текст:

String charsetName = "UTF-16"; // choose the apropriate charset.
CharBuffer cb =  Charsert.forName(charsetName).decode(mbb);
String text = cb.toString();
1 голос
/ 15 марта 2013

Отображенные байтовые буферы - самый быстрый способ:

 FileInputStream f = new FileInputStream( name );
FileChannel ch = f.getChannel( );
MappedByteBuffer mb = ch.map( ch.MapMode.READ_ONLY,
    0L, ch.size( ) );
byte[] barray = new byte[SIZE];
long checkSum = 0L;
int nGet;
while( mb.hasRemaining( ) )
{
    nGet = Math.min( mb.remaining( ), SIZE );
    mb.get( barray, 0, nGet );
    for ( int i=0; i<nGet; i++ )
    checkSum += barray[i];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...