Почему чтение файла по одному байту через FileInputStream радикально медленнее, чем через BufferedInputStream?
- Зачем нужна буферизация при вводе-выводе?
- Зачем нужна буферизация при вводе-выводе и что происходит, если читать файл без неё?
Дорог не байт, а системный вызов с переходом в ядро. Чтение по байту из FileInputStream — по вызову на байт; BufferedInputStream читает блок (8 КБ) за один вызов и отдаёт байты из памяти — разница на порядки.
- При записи то же — плюс flush() перед закрытием или ожиданием ответа
- Читать массивами (read(byte[])) — тот же эффект без обёртки
- Files.readAllBytes, transferTo — уже эффективны
А ещё Забытый flush — данные «потерялись» в буфере
Подробно
Системный вызов требует переключения контекста между пользовательским режимом и ядром, и его стоимость на порядки превышает копирование байта из памяти. Буферизующая обёртка читает блок разом и обслуживает последующие обращения из него. Ровно тот же принцип действует при записи, с важным дополнением: данные остаются в буфере, пока он не заполнится, поэтому забытые flush или close приводят к потере хвоста файла — try-with-resources решает и это. Стоит помнить, что буферизация не бесплатна и не всегда нужна: если вы и так читаете крупными массивами, дополнительный слой лишь копирует данные ещё раз.
Что хотят услышать
- Стоимость системного вызова.
- Как буфер её снимает.
- flush при записи.
Частые ошибки
- Забыть закрыть или сбросить буферизованный поток записи и потерять данные.
- Оборачивать в буфер поток, который и так читается большими блоками.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗FileInputStream проверяет права доступа к файлу при каждом обращении
- ✓Каждый байт — системный вызов, а буфер читает блоками
- ✗BufferedInputStream использует несколько потоков для чтения
- ✗Буферизация сжимает данные, поэтому их меньше
Что спросят дальше
- Что произойдёт, если не вызвать close у BufferedWriter?
- Где в этой конструкции проявляется паттерн Decorator?
- Почему у BufferedReader есть readLine, а у InputStream нет?
- Когда буферизация не нужна или даже вредна?
Разбор темы
- Потоки ввода-вывода: байты, символы, буферы
Байтовые и символьные потоки, кодировки и Charset, буферизация и системные вызовы, декоратор-паттерн и современный файловый API.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.