Reader / Writer
InputStream/OutputStream работают с байтами. Reader/Writer — с символами (текстом). Разница важна: один русский символ в UTF-8 занимает 2–4 байта. Если читать байтами и пытаться выводить как текст — кракозябры. Reader сам занимается декодированием байт → символы.
// Читаем текстовый файл
try (Reader reader = new FileReader("text.txt", StandardCharsets.UTF_8)) {
int c;
while ((c = reader.read()) != -1) {
System.out.print((char) c);
}
}
// Пишем текст в файл
try (Writer writer = new FileWriter("output.txt", StandardCharsets.UTF_8)) {
writer.write("Привет, мир!");
}
На практике почти всегда используют обёртки для удобства:
// BufferedReader — читать построчно
try (BufferedReader br = new BufferedReader(
new FileReader("log.txt", StandardCharsets.UTF_8))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
// PrintWriter — писать с println / printf
try (PrintWriter pw = new PrintWriter(
new FileWriter("report.txt", StandardCharsets.UTF_8))) {
pw.println("Строка 1");
pw.printf("Число: %d%n", 42);
}
Копнуть глубже
InputStreamReader — мост между байтами и символами. Когда у вас InputStream (например, от HTTP-соединения) но нужно читать текст — оборачиваете в InputStreamReader с явной кодировкой:
InputStream raw = httpConnection.getInputStream();
BufferedReader text = new BufferedReader(
new InputStreamReader(raw, StandardCharsets.UTF_8)
);
Никогда не используйте new FileReader("file.txt") без указания кодировки — он возьмёт системную кодировку платформы, и на разных машинах поведение разное. Всегда явно: StandardCharsets.UTF_8.
System.in, System.out, System.err — тоже потоки:
System.in—InputStream(байты с клавиатуры)System.out—PrintStream(байтовый, но с методами как у PrintWriter)Scanner(System.in)— удобная обёртка для чтения с консоли
StringWriter и StringReader — когда нужно «писать в строку» через Writer-интерфейс:
StringWriter sw = new StringWriter();
sw.write("Hello");
sw.write(" World");
String result = sw.toString(); // "Hello World"
Полезно для тестирования кода, который принимает Writer.
• почему нужно явно указывать кодировку и как сделать мост из InputStream в Reader (если дошёл до 2-го слоя).