Более быстрый способ чтения файла
Я работаю над программой, содержащей около 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 минут.
Я пытаюсь найти что-то еще намного быстрее.
У кого-нибудь есть представление о чем-то лучше?
Спасибо.
Ответы
Ответ 1
Вы должны найти ответ здесь:
http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly
Для лучшей производительности чтения Java необходимо запомнить четыре вещи:
-
Сведение к минимуму операций ввода-вывода путем чтения массива за раз, а не байта за раз. Массив 8 Кбайт - хороший размер.
-
Минимизировать вызовы методов, получая данные массивом за раз, а не байтом за раз. Используйте индексирование массива для получения байтов в массиве.
-
Минимизировать блокировки синхронизации потоков, если вам не нужна безопасность потоков. Либо сделайте меньше вызовов методов в потокобезопасном классе, либо используйте небезопасный класс, например FileChannel и MappedByteBuffer.
-
Минимизировать копирование данных между JVM/OS, внутренними буферами и массивами приложений. Используйте FileChannel с отображением памяти или прямым или завернутым массивом ByteBuffer.
Ответ 2
Поскольку вы не даете слишком много подробностей, я могу предложить вам использовать файлы с памятью, использующие память:
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
}
Можно опираться на него, если вы подробно расскажете о том, какие данные имеют ваши файлы.
ИЗМЕНИТЬ
Где//доступ к дате с использованием mbb, вы холодно декодируете свой текст:
String charsetName = "UTF-16"; // choose the apropriate charset.
CharBuffer cb = Charsert.forName(charsetName).decode(mbb);
String text = cb.toString();
Ответ 3
Буферы с байт-байтами - самый быстрый способ:
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];
}