Java 缓冲流
在Java的IO操作中,缓冲流是一种非常重要且常用的流类型。它能够显著提高IO操作的效率,是Java程序员必须掌握的基础知识之一。本文将详细介绍Java缓冲流的概念、用法和实际应用场景。
什么是缓冲流?
缓冲流(Buffered Stream)是处理流的一种,它可以为其他流提供缓冲功能,以提高IO操作的效率。
缓冲就是在内存中开辟一块区域,用于临时存储数据。当数据达到一定量时,再一次性写入或读取,减少访问磁盘的次数,从而提高效率。
没有缓冲的流每次读写操作都会直接访问物理设备,而缓冲流则会先将数据写入缓冲区,当缓冲区满了或手动刷新时才会真正写入物理设备,这样可以减少IO操作的次数,提高效率。
Java 缓冲流的分类
在Java中,缓冲流主要分为以下几种:
-
字节缓冲流
BufferedInputStream
:字节输入缓冲流BufferedOutputStream
:字节输出缓冲流
-
字符缓冲流
BufferedReader
:字符输入缓冲流BufferedWriter
:字符输出缓冲流
字节缓冲流
BufferedInputStream
BufferedInputStream
类为字节输入流提供缓冲功能,可以提高读取效率。
基本用法
try (FileInputStream fis = new FileInputStream("input.txt");
BufferedInputStream bis = new BufferedInputStream(fis)) {
int data;
while ((data = bis.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
构造方法
BufferedInputStream
提供了两个构造方法:
// 创建一个具有默认缓冲区大小的BufferedInputStream
BufferedInputStream(InputStream in)
// 创建一个具有指定缓冲区大小的BufferedInputStream
BufferedInputStream(InputStream in, int size)
BufferedOutputStream
BufferedOutputStream
类为字节输出流提供缓冲功能,可以提高写入效率。
基本用法
try (FileOutputStream fos = new FileOutputStream("output.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
String str = "Hello, BufferedOutputStream!";
byte[] bytes = str.getBytes();
bos.write(bytes);
// 注意:BufferedOutputStream会在缓冲区满或流关闭时自动刷新
// 但也可以手动调用flush()方法强制刷新
bos.flush();
} catch (IOException e) {
e.printStackTrace();
}
构造方法
BufferedOutputStream
也提供了两个构造方法:
// 创建一个具有默认缓冲区大小的BufferedOutputStream
BufferedOutputStream(OutputStream out)
// 创建一个具有指定缓冲区大小的BufferedOutputStream
BufferedOutputStream(OutputStream out, int size)
字符缓冲流
BufferedReader
BufferedReader
类为字符输入流提供缓冲功能, 它不仅提高了读取效率,还提供了方便的readLine()
方法来一次读取一行文本。
基本用法
try (FileReader fr = new FileReader("input.txt");
BufferedReader br = new BufferedReader(fr)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
构造方法
BufferedReader
提供了两个构造方法:
// 创建一个具有默认缓冲区大小的BufferedReader
BufferedReader(Reader in)
// 创建一个具有指定缓冲区大小的BufferedReader
BufferedReader(Reader in, int size)
BufferedWriter
BufferedWriter
类为字符输出流提供缓冲功能,它不仅提高了写入效率,还提供了newLine()
方法来写入一个平台相关的行分隔符。
基本用法
try (FileWriter fw = new FileWriter("output.txt");
BufferedWriter bw = new BufferedWriter(fw)) {
bw.write("Hello, BufferedWriter!");
bw.newLine(); // 写入一个行分隔符
bw.write("This is a new line.");
// 手动刷新
bw.flush();
} catch (IOException e) {
e.printStackTrace();
}
构造方法
BufferedWriter
也提供了两个构造方法:
// 创建一个具有默认缓冲区大小的BufferedWriter
BufferedWriter(Writer out)
// 创建一个具有指定缓冲区大小的BufferedWriter
BufferedWriter(Writer out, int size)
缓冲流的效率对比
为了直观地展示缓冲流的效率优势,我们通过一个简单的例子来对比使用缓冲流和不使用缓冲流的性能差异。
import java.io.*;
public class BufferedStreamDemo {
public static void main(String[] args) {
// 文件大小:约10MB
File sourceFile = new File("bigfile.txt");
File targetFile1 = new File("copy1.txt");
File targetFile2 = new File("copy2.txt");
try {
// 创建测试文件
if (!sourceFile.exists()) {
createTestFile(sourceFile);
}
// 测试不使用缓冲流
long start1 = System.currentTimeMillis();
copyWithoutBuffer(sourceFile, targetFile1);
long end1 = System.currentTimeMillis();
System.out.println("不使用缓冲流耗时:" + (end1 - start1) + "ms");
// 测试使用缓冲流
long start2 = System.currentTimeMillis();
copyWithBuffer(sourceFile, targetFile2);
long end2 = System.currentTimeMillis();
System.out.println("使用缓冲流耗时:" + (end2 - start2) + "ms");
} catch (IOException e) {
e.printStackTrace();
}
}
// 创建测试文件
private static void createTestFile(File file) throws IOException {
try (FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw)) {
for (int i = 0; i < 1000000; i++) {
bw.write("This is test line " + i + "\n");
}
}
}
// 不使用缓冲流复制文件
private static void copyWithoutBuffer(File source, File target) throws IOException {
try (FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(target)) {
int data;
while ((data = fis.read()) != -1) {
fos.write(data);
}
}
}
// 使用缓冲流复制文件
private static void copyWithBuffer(File source, File target) throws IOException {
try (FileInputStream fis = new FileInputStream(source);
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(target);
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
int data;
while ((data = bis.read()) != -1) {
bos.write(data);
}
}
}
}
输出示例:
不使用缓冲流耗时:15623ms
使用缓冲流耗时:187ms
从结果可以看出,使用缓冲流可以显著提高IO操作的效率。
缓冲流的高效主要来源于减少了与磁盘的交互次数。每次磁盘访问都涉及到寻道时间、旋转延迟等物理操作,这些都是非常耗时的。缓冲流通过在内存中缓存数据,减少了这些物理操作的次数,从而提高了效率。