Вопрос с собеседования · Java

Чем байтовые потоки отличаются от символьных?

JuniorВвод-вывод и NIO
Ещё спрашивают так:
  • Чем InputStream отличается от Reader?
  • Почему важно указывать кодировку при чтении файла?
Коротко

Байтовые потоки (InputStream/OutputStream) — для любых двоичных данных, символьные (Reader/Writer) — для текста и учитывают кодировку.

  • Символ и байт — не одно и то же: в UTF-8 буква занимает 1–4 байта
  • Мост между мирами — InputStreamReader / OutputStreamWriter с явной кодировкой

А ещё Кодировку указывайте явно; с Java 18 по умолчанию UTF-8, раньше — системная

Подробно

В Java две иерархии классов ввода-вывода:

  • байтовые — InputStream и OutputStream: читают и пишут байты. Для картинок, архивов, сетевых протоколов, любых двоичных данных;
  • символьные — Reader и Writer: работают с символами и превращают байты в символы по кодировке.

Разделение нужно, потому что символ и байт — разные вещи. В UTF-8 латиница занимает один байт, кириллица — два, эмодзи — четыре. Если читать текст байтами кусками и превращать каждый кусок в строку, многобайтовые символы разрежутся на границах — получатся «кракозябры».

Мост между мирами — InputStreamReader и OutputStreamWriter, которым передают кодировку. Буферизация (BufferedReader) ускоряет чтение и даёт readLine().

Кодировку стоит указывать явно (StandardCharsets.UTF_8). До Java 18 по умолчанию бралась кодировка системы, и одна и та же программа читала файл по-разному на Windows и Linux. С Java 18 по умолчанию UTF-8.

Для простых задач удобны Files.readString, Files.readAllLines, Files.newBufferedReader.

Пример

try (var reader = Files.newBufferedReader(Path.of("users.csv"), StandardCharsets.UTF_8)) {
    String line;
    while ((line = reader.readLine()) != null) { process(line); }
}

byte[] image = Files.readAllBytes(Path.of("logo.png")); // двоичные данные

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

  • Байтовые для двоичных данных, символьные для текста.
  • Почему важна кодировка и что ломается без неё.
  • Мост InputStreamReader и явное указание кодировки.

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

  • Читать текст побайтово и разрезать многобайтовые символы.
  • Не указывать кодировку явно.

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

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

Показать варианты и ответ
  • ✗Байтовые работают быстрее, но теряют часть данных
  • ✗Символьные потоки — лишь медленная обёртка над байтовыми, другой разницы между ними нет
  • ✓Байтовые — для любых двоичных данных, символьные — для текста с кодировкой
  • ✗Символьные предназначены только для консоли и терминала

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

  • Зачем нужна буферизация при чтении?
  • Чем опасна кодировка по умолчанию?

Разбор темы

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

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования