InputStream / OutputStream
I/O (Input/Output) — чтение и запись данных: файлы, сеть, память. Java работает с данными через потоки (streams) — не путать со Stream API! Здесь поток — это непрерывная последовательность байт, которую можно читать или писать.
Два направления:
InputStream— читаем откуда-то (файл, сеть, память)OutputStream— пишем куда-то (файл, сеть, память)
// Читаем файл байт за байтом
try (InputStream in = new FileInputStream("data.bin")) {
int b;
while ((b = in.read()) != -1) { // -1 = конец файла
System.out.print(b);
}
}
// Пишем байты в файл
try (OutputStream out = new FileOutputStream("result.bin")) {
out.write(new byte[]{72, 101, 108, 108, 111}); // "Hello" в байтах
}
try-with-resources закрывает поток автоматически — так и нужно всегда делать, иначе файл останется заблокированным.
Буферизация — читать по одному байту медленно (каждый вызов read() = системный вызов). BufferedInputStream читает сразу блоками в память:
try (InputStream in = new BufferedInputStream(new FileInputStream("big.bin"))) {
// теперь читает по 8KB за раз — в разы быстрее
}
Копнуть глубже
Паттерн Decorator в I/O. Потоки в Java устроены как матрёшки — один оборачивает другой, добавляя функциональность. Это и есть паттерн Decorator:
new DataOutputStream( // умеет писать int, double, String
new BufferedOutputStream( // буферизует
new FileOutputStream("f"))) // пишет в файл
Каждый слой добавляет одну ответственность, не меняя интерфейс — любой OutputStream можно обернуть в любой другой.
Иерархия основных классов:
ByteArrayOutputStream полезен когда нужно собрать байты в памяти, а не в файл — например, сериализовать объект и отправить по сети:
ByteArrayOutputStream buf = new ByteArrayOutputStream();
// ... пишем в buf ...
byte[] bytes = buf.toByteArray(); // забираем результат
• что такое буферизация и паттерн Decorator в контексте I/O (если дошёл до 2-го слоя).