BufferedOutputStream: примеры (JAVA)
BufferedOutputStream(OutputStream out)Общее описание BufferedOutputStream
Класс java.io.BufferedOutputStream предоставляет буферизированную обёртку вокруг любого потока вывода типа OutputStream. Цель - уменьшить число системных вызовов при множественных операциях записи путём накопления данных в памяти и единоразовой записи большого блока в базовый поток.
Когда используется: при записи в файлы, сетевые сокеты или другие потоки, где множество мелких операций записи приводит к накладным расходам. Особенно полезен при записи байтовых массивов или последовательного вывода данных.
Конструкторы и основные методы
BufferedOutputStream(OutputStream out)- Аргументы:
out- базовый поток для записи. Не возвращает значение. - Поведение: создаёт буфер по умолчанию (обычно 8192 байт).
- Аргументы:
BufferedOutputStream(OutputStream out, int size)- Аргументы:
out- базовый поток;size- размер буфера в байтах. - Возвращаемое значение: конструктор - объект класса.
- Особенности: если
size <= 0, выбрасываетсяIllegalArgumentException.
- Аргументы:
void write(int b)- Аргументы: байт для записи (только младшие 8 бит используются).
- Поведение: помещает байт в внутренний буфер; при переполнении буфер сбрасывается в базовый поток.
- Исключения: может выбросить
IOExceptionпри ошибках базового потока.
void write(byte[] b, int off, int len)- Аргументы: массив байт, смещение и длина записи.
- Поведение: копирует указанный диапазон в буфер; если длина превышает размер буфера, данные могут быть записаны напрямую в базовый поток без промежуточного копирования.
- Исключения:
IOException,IndexOutOfBoundsExceptionпри неверных off/len,NullPointerExceptionпри null-массиве.
void flush()- Аргументы: нет.
- Поведение: немедленно сбрасывает содержимое буфера в базовый поток и вызывает соответствующие операции у него; полезно для гарантированной доставки данных (например, в сеть).
- Исключения:
IOException.
void close()- Аргументы: нет.
- Поведение: сначала выполняется
flush(), затем закрывается базовый поток. После закрытия дальнейшие вызовы записывающих методов приведут кIOException. - Исключения:
IOException.
Возвращаемых значений у методов записи нет (void). Исключения главная сигнальная механика при ошибках.
Ограничения и свойства
- Буфер не синхронизирован; при конкурентном доступе требуется внешняя синхронизация.
- Не подходит для символьной записи без преобразования байтов (использовать
OutputStreamWriterилиBufferedWriterдля текста).
Короткие примеры использования
Пример 1. Запись массива байт в файл (по умолчанию буфер)
import java.io.*;
public class Example1 {
public static void main(String[] args) throws IOException {
byte[] data = "Привет, BufferedOutputStream!".getBytes("UTF-8");
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("out1.bin"))) {
bos.write(data);
}
// Файл out1.bin создан
}
}
Результат: файл out1.bin со строкой в кодировке UTF-8; программа завершается без вывода в консоль.
Пример 2. Указание собственного размера буфера и запись по одному байту
import java.io.*;
public class Example2 {
public static void main(String[] args) throws IOException {
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("out2.bin"), 1024)) {
for (int i = 0; i < 100; i++) bos.write(i); // записи собираются в буфер
bos.flush(); // опционально, т.к. close() также выполнит flush
}
}
}
Результат: out2.bin содержит первые 100 байтов (0..99).
Пример 3. Буферизированная запись в сетевой сокет
import java.io.*;
import java.net.*;
public class Example3Client {
public static void main(String[] args) throws Exception {
try (Socket s = new Socket("example.com", 80);
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream())) {
String req = "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n";
bos.write(req.getBytes("UTF-8"));
bos.flush();
// далее чтение ответа через InputStream
}
}
}
Результат: сформированный HTTP-запрос отправлен в один или несколько системных вызовов, эффективность выше, чем при построчной отправке без буфера.
Похожие инструменты в Java
- BufferedWriter - буфер для символьного вывода. Предпочтителен при работе с текстом и указании кодировки через
OutputStreamWriter. - FileOutputStream - низкоуровневый поток, лучше использовать вместе с буфером для производительности.
- DataOutputStream - добавляет методы для записи примитивов (int, long и т. п.). Часто комбинируется с буфером:
new DataOutputStream(new BufferedOutputStream(...)). - java.nio.channels.FileChannel и ByteBuffer - альтернативный подход через NIO; уместен при необходимости прямого управления буферами и более тонкой производительности.
Выбор зависит от задачи: для текстовой записи - BufferedWriter; для примитивов и структурированных данных - DataOutputStream + BufferedOutputStream; для высокопроизводительных и неблокирующих операций - NIO.
Аналоги в других языках и их особенности
- Python:
io.BufferedWriter. Оборачивает файловый объект, имеет методыwrite,flush,close. Пример:import io with open('py_out.bin','wb') as f: with io.BufferedWriter(f, buffer_size=8192) as bw: bw.write(b'Hello from Python')Результат: файл py_out.bin с указанными байтами.
- Node.js (JavaScript):
fs.createWriteStream(path, { highWaterMark: 8192 }). Поток пишет с контролем буферного порога; методwriteвозвращает булево значение, сигнализирующее о заполнении внутреннего буфера.const fs = require('fs'); const ws = fs.createWriteStream('node_out.bin', { highWaterMark: 8192 }); ws.write(Buffer.from('Hello from Node')); ws.end();Результат: node_out.bin создан.
- C#:
System.IO.BufferedStream, конструктор принимает базовыйStreamи размер буфера. Поведение и API очень похожи на Java.using(var fs = File.Create("csharp_out.bin")) using(var bs = new BufferedStream(fs, 8192)) { byte[] b = System.Text.Encoding.UTF8.GetBytes("Hello C#"); bs.Write(b,0,b.Length); }Результат: csharp_out.bin с данными.
- Go:
bufio.NewWriter. Возвращает писатель с методомFlush().package main import ( "bufio" "os" ) func main(){ f,_:=os.Create("go_out.bin") w:=bufio.NewWriterSize(f,8192) w.Write([]byte("Hello Go")) w.Flush() f.Close() }Результат: go_out.bin с данными.
- PHP: потоки PHP имеют собственную буферизацию, но можно управлять через
stream_set_write_buffer($stream, $buffer).$f = fopen('php_out.bin','wb'); stream_set_write_buffer($f, 8192); fwrite($f, "Hello PHP"); fclose($f);Результат: php_out.bin создан.
- Lua: стандартный io имеет внутренную буферизацию; явного BufferedOutputStream нет; можно использовать
file:writeиfile:flush(). - Kotlin: использует Java-реализацию:
BufferedOutputStreamиз JDK; синтаксис Kotlin компактнее.
Отличия: во многих языках концепция аналогична - обёртка вокруг базового потока с внутренним буфером. Node.js дополнительно возвращает сигнал о заполнении буфера через результат write. Python и Go дают явный flush, как и Java.
Типичные ошибки и примеры
Ошибка 1. Забыт flush/close - потеря данных
import java.io.*;
public class Error1 {
public static void main(String[] args) throws Exception {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("err1.bin"));
bos.write("data".getBytes());
// bos.close() забыли
}
}
Результат: файл err1.bin может быть пустым или неполным, данные остались в буфере.
Ошибка 2. Переиспользование закрытого потока
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("err2.bin"))) {
bos.write(1);
}
// далее
// bos.write(2); // компилятор не даст, но если попытаться через ссылку - IOException
Результат: при записи в закрытый поток будет выброшено IOException.
Ошибка 3. Неверные off/len при использовании write(byte[], off, len)
byte[] data = new byte[10];
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("err3.bin"));
bos.write(data, 5, 10); // IndexOutOfBoundsException
Результат: вылет исключения IndexOutOfBoundsException до записи.
Ошибка 4. Ожидание возвращаемого количества записанных байт
// Неверно ожидать возвращаемое значение
bos.write(data); // возвращает void, нет числа записанных байт
Результат: неправильная логика, код не получает подтверждение от write о числе записанных байт, требуется внешняя проверка/исключения.
Изменения за последние версии Java
Класс BufferedOutputStream является частью пакета java.io с ранних версий JDK и не претерпевал значительных изменений в последних релизах. Основные аспекты остаются прежними: конструкторы, поведение буферизации, методы write, flush, close.
В современных версиях Java улучшения в общем случае коснулись производительности подсистем ввода-вывода и реализации низкоуровневых потоков, но публичный API BufferedOutputStream не изменялся и не помечен как устаревший.
Расширенные и редкие варианты применения
Пример 1. Комбинация с GZIPOutputStream для компрессии с буферизацией
import java.io.*;
import java.util.zip.GZIPOutputStream;
public class Adv1 {
public static void main(String[] args) throws Exception {
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("data.gz"));
GZIPOutputStream gzos = new GZIPOutputStream(bos)) {
gzos.write("Большой текст для сжатия".getBytes("UTF-8"));
// GZIPOutputStream.flush() вызовет запись в bos при необходимости
}
}
}
Результат: data.gz - сжатый файл. Буферизация перед gzip уменьшает число операций записи в файл.
Пример 2. Подсчёт записанных байт через наследование
import java.io.*;
class CountingBufferedOutputStream extends BufferedOutputStream {
private long count = 0;
public CountingBufferedOutputStream(OutputStream out, int size) { super(out, size); }
@Override
public synchronized void write(int b) throws IOException {
super.write(b);
count++;
}
@Override
public synchronized void write(byte[] b, int off, int len) throws IOException {
super.write(b, off, len);
count += len;
}
public long getCount() { return count; }
}
public class Adv2 {
public static void main(String[] args) throws Exception {
try (CountingBufferedOutputStream cbos = new CountingBufferedOutputStream(new FileOutputStream("count.bin"), 4096)) {
cbos.write(new byte[1000]);
System.out.println(cbos.getCount());
}
}
}
Результат: в консоль выведется число 1000; файл count.bin содержит 1000 нулевых байтов.
Пример 3. Буферизация для сетевого протокола с принудительным сбросом по окончании сообщения
// Сценарий: отправлять сообщения, заканчивая '
', и немедленно отправлять их в сеть
try (Socket s = new Socket(host, port);
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream())) {
String msg = "EVENT:123\n";
bos.write(msg.getBytes("UTF-8"));
bos.flush(); // гарантирует доставку события
}
Результат: каждое сообщение приходит на сервер без долгого ожидания; flush используется для границ сообщений.
Пример 4. Сравнение производительности: с буфером и без
// Укорочённый пример измерения
long t1 = System.currentTimeMillis();
try (OutputStream os = new FileOutputStream("plain.bin")) {
for (int i=0;i<1_000_000;i++) os.write(i);
}
long t2 = System.currentTimeMillis();
try (OutputStream os = new BufferedOutputStream(new FileOutputStream("buf.bin"))) {
for (int i=0;i<1_000_000;i++) os.write(i);
}
long t3 = System.currentTimeMillis();
System.out.println("plain: " + (t2-t1) + " ms, buffered: " + (t3-t2) + " ms");
Результат: plain обычно значительно медленнее, buffered даёт заметный выигрыш; точные числа зависят от системы.
Пояснения
- Комбинация с компрессией и подсчётом полезна для логирования, резервного копирования и сетевой передачи больших объёмов.
- При использовании в многопоточных приложениях требуется внешняя синхронизация, либо использовать отдельные потоки/синхронизированные блоки.
- Выбор размера буфера зависит от характера операций: слишком маленький - высокая нагрузка; слишком большой - ненужное потребление памяти.
джава BufferedOutputStream function comments
- джава BufferedOutputStream - аргументы и возвращаемое значение
- Функция java BufferedOutputStream - описание
- BufferedOutputStream - примеры
- BufferedOutputStream - похожие методы на java
- BufferedOutputStream на javascript, c#, python, php
- BufferedOutputStream изменения java
- Примеры BufferedOutputStream на джава