缓冲流

Java非缓冲流的每次读写都需要进行本地方法调用,交给底层操作系统进行处理,工作效率非常低, 因为每次请求可能都会触发磁盘读写、网络活动以及其它一些开销昂贵的操作。为了减少操作系统的负载,Java提供了IO缓冲流,缓冲流内部提供了缓冲区(buffer)进行读写,大部分缓冲流的buffer默认 大小为 8192 字节(8KB)。

  • 缓冲输入流从内存区域的buffer读取数据,当buffer数据为空时,Java本地输入方法才会进行调
    用。
  • 缓冲输出流将数据写入到内存区域的buffer,当buffer写满时,Java本地输出方法才会进行调用。

Java程序可以通过包装方式将非缓冲流构造成为一个缓冲流,BufferedInputStream、 BufferedOutputStream用于构造缓冲字节流,BufferedReader、BufferedWriter用于构造缓冲字符流。

字节缓冲流

字节缓冲流主要包括缓冲输入流BufferedInputStream,缓冲输出流BufferedOutputStreamWriter。

  • BufferedInputStream通过非缓冲字节流FileInputStream进行一次磁盘IO,一次性读取多个字节
    数据到内存buffer(字节数组),后续程序只需从内存中的buffer数组中读取字节数据,减少IO操作次
    数。
public class BufferedInputStreamDemo {

public static void main(String[] args) {
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("D://test/source.txt"))) {
int c;
// 从内存buffer中读取字节数据,如果buffer为空,才会进行IO操作
while((c = bis.read()) != -1) {
System.out.println(c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

BufferedInputStream通过FileInputStream提供的本地方法readBytes,可以通过一次IO操作读取多个字节数据。

  • BufferedOutputStream通过非缓冲字节流FileOutputStream进行一次磁盘IO,将内存缓冲区
    buffer中的多个字节数据一次性写入文件中,减少IO操作次数。
public class BufferedOutputStreamDemo {

public static void main(String[] args) {
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("D://test/target.txt"))) {
// 写入字符 '2' 到内存buffer
bos.write(50);
// 写入字符 '0' 到内存buffer
bos.write(48);
// 写入字符 '2' 到内存buffer
bos.write(50);
// 写入字符 '3' 到内存buffer
bos.write(51);
// 可在此 sleep 10s,去检测文件内容, 10s后调用了flush方法文件内容才写入
// try {
// Thread.sleep(10000);
// } catch (Exception e) {
// e.printStackTrace();
// }
// 刷新输出流,将内存buffer数据写到文件中
// 缓冲流的close方法调用时,会先自动调用一次flush方法,强制将数据写出
// 但是明确后续没有数据可写时,最好养成良好习惯,手动调用一次flush方法
bos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}

BufferedOutputStream此时依赖的方法是非缓冲字节流FileOutputStream提供的本地方法writeBytes。

字符缓冲流

字符缓冲流主要包括缓冲输入流BufferedReader,缓冲输出流BufferedWriter。

  • BufferedReader可基于InputStreamReader、FileReader等非字符缓冲流构造。
public class BufferedReaderDemo {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("D://test/source.txt"))) {
String line;
// 按行读取,自动处理回车换行符
while((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

基于FileReader构造BufferedReader

BufferedReader br = new BufferedReader(new FileReader("D://test/source.txt"))
  • BufferedWriter可基于OutputStreamReader、FileWriter等非字符缓冲流构造。
public class BufferedWriterDemo2 {

public static void main(String[] args) {
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("D://test/target.txt")))) {
bw.write("2023");
// windows换行符
// bw.write("\r\n");
bw.newLine();
bw.write("2023");
bw.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}

基于FileWriter构造BufferedWriter

1 BufferedWriter bw = new BufferedWriter(new FileWriter("D://test/target.txt"))

基于PrintWriter构造BufferedWriter

1 BufferedWriter bw = new BufferedWriter(new PrintWriter(new FileWriter("D://test/

flush方法是属于输出流的方法,调用非缓冲流的flush方法不会产生任何作用。