Java BufferedOutputStream 类
最后修改时间:2025 年 4 月 16 日
java.io.BufferedOutputStream 类为另一个输出流添加缓冲功能。它通过减少本机 I/O 调用次数来提高性能。数据从缓冲区以大块形式写入底层流。
BufferedOutputStream 包装另一个 OutputStream 并提供缓冲写入功能。默认缓冲区大小为 8192 字节(8KB),但可以指定自定义大小。此类是线程安全的,可用于并发访问。
BufferedOutputStream 类概述
BufferedOutputStream 扩展了 FilterOutputStream 并提供了缓冲输出操作。关键方法包括写入操作和刷新功能。缓冲区在写入底层流之前会填充数据。
public class BufferedOutputStream extends FilterOutputStream {
public BufferedOutputStream(OutputStream out);
public BufferedOutputStream(OutputStream out, int size);
public synchronized void write(int b);
public synchronized void write(byte[] b, int off, int len);
public synchronized void flush();
public void close();
}
上面的代码显示了 BufferedOutputStream 提供的关键方法。这些方法允许使用缓冲进行高效的数据写入。flush 方法确保所有缓冲数据都写入底层流。
创建 BufferedOutputStream
通过将 BufferedOutputStream 包装在另一个 OutputStream 周围来创建它。您可以指定缓冲区大小或使用默认值。缓冲区大小会影响 I/O 性能 - 较大的缓冲区减少本机调用,但会使用更多内存。
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Main {
public static void main(String[] args) {
try {
// Create with default buffer size
OutputStream fileStream = new FileOutputStream("output.txt");
BufferedOutputStream bufferedStream1 =
new BufferedOutputStream(fileStream);
// Create with custom buffer size (16KB)
OutputStream fileStream2 = new FileOutputStream("output2.txt");
BufferedOutputStream bufferedStream2 =
new BufferedOutputStream(fileStream2, 16384);
System.out.println("Default buffer stream created");
System.out.println("Custom buffer (16KB) stream created");
bufferedStream1.close();
bufferedStream2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
此示例演示了创建 BufferedOutputStream 的不同方法。第一个使用默认缓冲区大小,而第二个指定 16KB。完成操作后始终关闭流以释放资源。关闭 BufferedOutputStream 时,会自动关闭底层 FileOutputStream。
使用 BufferedOutputStream 写入数据
BufferedOutputStream 提供了几种写入数据的方法。最简单的方法是写入单个字节。更有效的方法是从数组写入多个字节。所有写入操作都同步以确保线程安全。
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try (BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream("output.txt"))) {
// Write single bytes
bos.write('H');
bos.write('e');
bos.write('l');
bos.write('l');
bos.write('o');
// Flush to ensure data is written
bos.flush();
System.out.println("Data written to file");
} catch (IOException e) {
e.printStackTrace();
}
}
}
此示例演示了如何使用 BufferedOutputStream 逐字节写入数据。try-with-resources 语句确保正确关闭流。flush 方法确保所有缓冲数据都立即写入底层流。
写入字节数组
为了获得更好的性能,请一次从字节数组写入多个字节。这减少了方法调用和本机 I/O 操作。缓冲区会自动处理大型写入的分块。
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try (BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream("data.bin"))) {
byte[] data = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
// Write entire array
bos.write(data);
// Write partial array (bytes 2-5)
bos.write(data, 2, 4);
System.out.println("Byte arrays written to file");
} catch (IOException e) {
e.printStackTrace();
}
}
}
此示例演示了写入完整和部分字节数组。第一个写入操作写入所有 8 个字节。第二个仅写入从索引 2 开始的 4 个字节。缓冲区会自动管理何时实际写入底层流。
刷新缓冲区
flush 方法强制将所有缓冲数据写入底层流。当需要及时写入时,这一点很重要。关闭流也会自动刷新缓冲区。
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try (BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream("log.txt"))) {
// Write log entries
bos.write("Starting application\n".getBytes());
// Important - ensure log entry is written immediately
bos.flush();
// Simulate work
for (int i = 0; i < 1000000; i++) {
// Some processing
}
bos.write("Work completed\n".getBytes());
System.out.println("Log entries written with explicit flush");
} catch (IOException e) {
e.printStackTrace();
}
}
}
此示例显示了刷新对于关键日志条目的重要性。第一个消息会立即刷新,以确保即使程序稍后崩溃也会写入。如果没有刷新,消息可能会保留在缓冲区中,直到缓冲区填满或流关闭。
性能比较
BufferedOutputStream 显着提高了小写入的性能。此示例比较了使用和不使用缓冲的写入。当有许多小写入时,差异变得明显。
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Main {
public static void main(String[] args) {
final int COUNT = 100000;
// Unbuffered write
long start = System.currentTimeMillis();
try (OutputStream os = new FileOutputStream("unbuffered.txt")) {
for (int i = 0; i < COUNT; i++) {
os.write(i % 256);
}
} catch (IOException e) {
e.printStackTrace();
}
long unbufferedTime = System.currentTimeMillis() - start;
// Buffered write
start = System.currentTimeMillis();
try (OutputStream os = new BufferedOutputStream(
new FileOutputStream("buffered.txt"))) {
for (int i = 0; i < COUNT; i++) {
os.write(i % 256);
}
} catch (IOException e) {
e.printStackTrace();
}
long bufferedTime = System.currentTimeMillis() - start;
System.out.println("Unbuffered time: " + unbufferedTime + " ms");
System.out.println("Buffered time: " + bufferedTime + " ms");
}
}
此性能测试写入 100,000 个单独的字节,有和没有缓冲。缓冲版本通常更快,因为它最大限度地减少了本机 I/O 调用。确切的速度差异取决于系统和存储介质。
写入文本数据
虽然 BufferedOutputStream 处理字节,但它通常与文本数据一起使用,方法是将字符串转换为字节。此示例演示了高效的文本写入以及正确的字符编码处理。
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class Main {
public static void main(String[] args) {
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("text.txt"))) {
String header = "User Log\n========\n";
bos.write(header.getBytes(StandardCharsets.UTF_8));
for (int i = 1; i <= 10; i++) {
String line = String.format("User %d logged in\n", i);
bos.write(line.getBytes(StandardCharsets.UTF_8));
}
System.out.println("Text file written with UTF-8 encoding");
} catch (IOException e) {
e.printStackTrace();
}
}
}
此示例演示了使用正确的 UTF-8 编码写入文本数据。每个字符串在写入之前都会转换为字节。缓冲使即使有许多小写入也能高效地进行。始终指定字符集以避免平台相关的默认设置。
来源
在本文中,我们介绍了 Java BufferedOutputStream 类的基本方法和特性。理解这些概念对于在 Java 应用程序中使用高效的 I/O 操作至关重要。
作者
列出所有Java教程。