Я использую следующие 2 кода для чтения большого файла.
Это с использованием FileReader:
File file = new File("/Users/Desktop/shakes.txt");
FileReader reader = new FileReader(file);
int ch;
long start = System.currentTimeMillis();
while ((ch = reader.read()) != -1) {
System.out.print((char) ch);
}
long end = System.currentTimeMillis();
И следующее при использовании BufferedReader:
File file = new File("/Users/Desktop/shakes.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));
int ch;
long start = System.currentTimeMillis();
while ((ch = reader.read()) != -1) {
System.out.print((char) ch);
}
long end = System.currentTimeMillis();
Исходя из документации для BufferedReader:
It is therefore advisable to wrap a BufferedReader around any Reader whose read() operations may be costly, such as FileReaders and InputStreamReaders. Without buffering, each invocation of read() or readLine() could cause bytes to be read from the file, converted into characters, and then returned, which can be very inefficient.
Учитывая эту документацию и размер буфера по умолчанию 8192 класса BufferedReader, не должно ли общее время чтения файла с помощью BufferedReader быть быстрее? В настоящее время оба фрагмента кода выполняются на моей машине за ~ 3000 мс. Однако, если я использую readLine в BufferedReader, производительность существенно улучшается (~ 200 мс).
Мысли о чем-то, чего мне не хватает? Разве не ожидается, что даже при использовании метода read () BufferedReader должен работать лучше, чем чтение из FileReader?




Использование BufferedReader действительно быстрее, чем использование только FileReader.
Я выполнил ваш код на своей машине со следующим текстовым файлом https://norvig.com/big.txt (6 МБ).
System.out.print() является узким местом (внутри цикла). Без печати результат в 4 раза быстрее с BufferedReader. 200 мс против 50 мс. (Сравните это с 17 секундами раньше)Другими словами, не используйте System.out.print() при тестировании.
Пример
Улучшенный тест может выглядеть так, используя StringBuilder.
File file = new File("/Users/Desktop/shakes.txt");
FileReader reader = new FileReader(file);
int ch;
StringBuilder sb = new StringBuilder();
long start = System.currentTimeMillis();
while ((ch = reader.read()) != -1) {
//System.out.print((char) ch);
sb.append((char) ch);
}
long end = System.currentTimeMillis();
System.out.println(sb);
Приведенный выше код обеспечивает тот же результат, но работает намного быстрее. Он точно покажет разницу в скорости при использовании BufferedReader.
Thoughts on something that I'm missing?
Должно быть быстрее читать файл по символу за раз с BufferedReader, чем с FileReader. (На порядки!) Так что я подозреваю, что проблема в ваших тестах.
Ваш тест измеряет как чтение файла, так и его запись в стандартный вывод. Таким образом, ваши показатели производительности будут искажены накладными расходами письмо файла. И если ваш вывод записывается на «консоль», то эти накладные расходы включают накладные расходы на рисование символов на экране ... и прокрутку.
Ваш тест не учитывает накладные расходы на запуск виртуальной машины.
Ваш тест (очевидно) не влияет на кеширование файлов. (При первом чтении файла он будет считан с диска. Если вы прочитаете его снова вскоре после этого, вы будете читать мая из копии файла, кэшированного в памяти операционной системой. Это будет быстрее.)
Спасибо, Стивен. Вы правы, и мне также удалось это проверить, удалив операторы System.out.
Спасибо за ответ, J.A.P! Я изменил свой код, чтобы избавиться от System.out, и BufferedReader действительно лучше, чем FileReader, и каждый раз почти на один и тот же фактор.