Ответ
InputStream и Reader — это абстрактные классы в Java для чтения данных, но они работают с разными единицами информации.
Ключевое отличие:
InputStreamпредназначен для чтения байтов (8 бит,byte). Он используется для бинарных данных (файлы, изображения, сетевые сокеты).Readerпредназначен для чтения символов (16 бит,char), т.е. текстовых данных. Он корректно обрабатывает кодировки символов.
Почему это важно? Символ (char) может кодироваться одним или несколькими байтами в зависимости от кодировки (UTF-8, Windows-1251). Reader выполняет это преобразование автоматически.
Иерархия и примеры:
// InputStream (для байтов)
InputStream is = new FileInputStream("data.bin");
int byteData = is.read(); // Читает один байт
// Reader (для символов/текста)
// FileReader использует кодировку по умолчанию платформы (часто рискованно)
Reader reader1 = new FileReader("text.txt");
// Лучше явно указывать кодировку через InputStreamReader
Reader reader2 = new InputStreamReader(
new FileInputStream("text.txt"),
StandardCharsets.UTF_8
);
int charData = reader2.read(); // Читает один символ (char)
Аналоги для записи: OutputStream (для байтов) и Writer (для символов).
Правило выбора:
- Используйте
InputStream/OutputStreamдля всего, что не является простым текстом (.jpg,.zip,.pdf, сериализованные объекты). - Используйте
Reader/Writer(с явно указанной кодировкой, например, UTF-8) для чтения и записи текстовых файлов (.txt,.html,.json,.xml).
Ответ 18+ 🔞
Давай разберём эту дичь, чтобы она в голове наконец улеглась, а не болталась как манда с ушами. Смотри, в чём тут суть.
Есть два главных абстрактных деда, с которых всё начинается: InputStream и Reader. И они, блядь, работают с принципиально разным добром, хоть оба и для чтения.
В чём, сука, разница, если по-простому?
InputStream— это для байтов. Для вот этой вот сырой, бинарной хуйни. Картинка, зип-архив, какой-нибудь.exeфайл, данные из сети — всё, что не текст в чистом виде. Он читает по одному байту (8 бит,byte). Представь, что ты пьёшь воду из шланга — глотаешь поток, не думая, из чего он состоит.Reader— это уже для символов (букв, знаков). Для текста, мать его. Он оперируетchar'ами (16 бит). И вот тут главный фокус: один символ (например, русская "ё" или смайлик) в файле может быть записан НЕСКОЛЬКИМИ байтами, в зависимости от кодировки (UTF-8, Windows-1251 и прочая пиздобратия).Reader— это такой умный переводчик, который берёт этот поток байтов и сам, ебушки-воробушки, собирает из них правильные символы, согласно указанной кодировке.InputStreamэтого делать не умеет — он тебе байты так и выдаст, а ты потом сам голову ломай.
Иерархия и как этим пользоваться, чтобы не обосраться:
// InputStream (для всего нетекстового, для байтов)
InputStream is = new FileInputStream("photo.jpg");
int byteData = is.read(); // Высосал один байт. Всё.
// Reader (для текста)
// Вариант 1: Наивный и опасный. FileReader возьмёт кодировку по умолчанию системы.
// Если файл в UTF-8, а система в CP1251 — получишь абракадабру. Доверяй, но проверяй, а лучше — не доверяй ни хуя.
Reader reader1 = new FileReader("text.txt");
// Вариант 2: Правильный и взрослый. Берём InputStream и насаживаем на него InputStreamReader,
// где явно, блядь, указываем кодировку. Теперь всё будет чётко.
Reader reader2 = new InputStreamReader(
new FileInputStream("text.txt"),
StandardCharsets.UTF_8 // Вот, сука, явно сказали!
);
int charData = reader2.read(); // Прочитал один целый символ (char), а не сранный байт.
Для записи, ясное дело, есть их антиподы: OutputStream (плюёт байтами) и Writer (вываливает символами).
Итоговое правило, которое надо выжечь на жопе:
InputStream/OutputStream— для всей не текстовой хуйни: картинки (jpg,png), архивы (zip), программы, PDF-ки.Reader/Writer— ТОЛЬКО для текста (txt,html,json,xml). И всегда, блядь, явно указывай кодировку (в идеале UTF-8), а не надейся на авось, а то потом волосы на жопе рвать будешь, разбираясь с кракозябрами.