Получить доступ

Почему чтение файла по одному байту через FileInputStream радикально медленнее, чем через BufferedInputStream?

MiddleВвод-вывод и NIO
Ещё спрашивают так:
  • Зачем нужна буферизация при вводе-выводе?
  • Зачем нужна буферизация при вводе-выводе и что происходит, если читать файл без неё?
Коротко

Дорог не байт, а системный вызов с переходом в ядро. Чтение по байту из FileInputStream — по вызову на байт; BufferedInputStream читает блок (8 КБ) за один вызов и отдаёт байты из памяти — разница на порядки.

  • При записи то же — плюс flush() перед закрытием или ожиданием ответа
  • Читать массивами (read(byte[])) — тот же эффект без обёртки
  • Files.readAllBytes, transferTo — уже эффективны

А ещё Забытый flush — данные «потерялись» в буфере

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Системный вызов требует переключения контекста между пользовательским режимом и ядром, и его стоимость на порядки превышает копирование байта из памяти. Буферизующая обёртка читает блок разом и обслуживает последующие обращения из него. Ровно тот же принцип действует при записи, с важным дополнением: данные остаются в буфере, пока он не заполнится, поэтому забытые flush или close приводят к потере хвоста файла — try-with-resources решает и это. Стоит помнить, что буферизация не бесплатна и не всегда нужна: если вы и так читаете крупными массивами, дополнительный слой лишь копирует данные ещё раз.

Что хотят услышать

  • Стоимость системного вызова.
  • Как буфер её снимает.
  • flush при записи.

Частые ошибки

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

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✓Каждое чтение оборачивается системным вызовом; буфер читает крупными блоками и отдаёт байты из памяти
  • ✗BufferedInputStream использует несколько потоков для чтения
  • ✗FileInputStream проверяет права доступа при каждом обращении
  • ✗Буферизация сжимает данные, поэтому их меньше

Что спросят дальше

  • Что произойдёт, если не вызвать close у BufferedWriter?
  • Где в этой конструкции проявляется паттерн Decorator?
  • Почему у BufferedReader есть readLine, а у InputStream нет?
  • Когда буферизация не нужна или даже вредна?

Разбор темы

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем