В чем преимущество использования буферизированных потоков (BufferedInputStream/BufferedOutputStream) в Java?

«В чем преимущество использования буферизированных потоков (BufferedInputStream/BufferedOutputStream) в Java?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Буферизированные потоки (BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter) добавляют к базовым потокам буфер в памяти, что значительно повышает производительность операций ввода-вывода.

Основная проблема, которую они решают: Прямое чтение/запись каждого байта (символа) — это дорогой системный вызов. Буферизация позволяет работать с данными блоками.

Преимущества:

  1. Снижение количества системных вызовов. Вместо тысячи обращений к диску для чтения 1000 байт, буфер (например, 8 КБ) заполняется за один вызов, и дальнейшее чтение происходит из памяти.
  2. Повышение производительности. Особенно заметно при работе с файлами, сетью или другими "медленными" источниками данных.

Пример чтения файла с буферизацией:

try (FileInputStream fis = new FileInputStream("large_file.dat");
     BufferedInputStream bis = new BufferedInputStream(fis, 16384)) { // Буфер 16 КБ

    byte[] buffer = new byte[1024];
    int bytesRead;
    // read() теперь считывает данные из внутреннего буфера, а не с диска
    while ((bytesRead = bis.read(buffer)) != -1) {
        processData(buffer, bytesRead);
    }
} // Потоки закроются автоматически (try-with-resources)

По умолчанию размер буфера составляет 8 КБ (8192 байта), но его можно задать явно в конструкторе.

Важно: Буферизированные потоки — это декораторы. Они оборачивают другой поток (InputStream/OutputStream) и добавляют к нему функциональность буферизации.