信息

缓冲流:普通的流每读写一次就要与磁盘进行一次 IO 操作,且每次只能从操作一个字节、字符,效率低且耗时。缓冲流是提前在内存中开辟一块区域,一次读取或写入大量数据再进行 IO 操作,减少磁盘交互,优化读写速率。

1 实现原理

缓冲区:缓冲流内部维护了一个字节数组 (默认大小为 8 KB),作为临时缓冲区。

  1. 初始化时,从底层的 InputStream 读取一批数据 (填写到缓冲区);
  2. 调用 read 方法时,实际从缓冲区取数据,缓冲区空了后再进行下一批数据读取;
  3. 同理,OutputStream 会先写入到缓冲区,满了或者刷新(flush/close)后, 才一次行写入底层流。
  • 读数据:先从磁盘/网络一次性读一批数据到内容缓冲区,后续读取直接从缓冲区取,缓冲区空了再读取一次;
  • 写数据:先写到内存缓冲区,缓冲区满了或手动刷新 flush 时,再一次写入磁盘/网络。

2 分类

类型字节缓冲流字符缓冲流
输入流BufferedInputStreamBufferedReader
输出流BufferedOutputStreamBufferedWriter

3 代码示例

3.1.1 从缓冲区读取

public static void main(String[] args) {  
    String srcPath = "F:\\allFile\\01 temp\\1.txt";  
    String targetPath = "F:\\allFile\\01 temp\\2.txt";  
  
    try(  
            FileInputStream inputStream = new FileInputStream(srcPath);  
            FileOutputStream outputStream = new FileOutputStream(targetPath);  
  
            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);  
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);  
            ){  
        byte[] buffer = new byte[1024]; // 临时数组(可选,缓冲流已自带缓冲区)  
        int len; // 每次读取的字节数  
  
        // 从缓冲输入流读数据,直到末尾(返回 -1)  
        while ((len = bufferedInputStream.read(buffer)) != -1){  
            bufferedOutputStream.write(buffer, 0, len);  
        }  
    } catch (IOException e) {  
        throw new RuntimeException(e);  
    }  
}

3.1.2 从行读取

public static void main(String[] args) {  
    String srcPath = "F:\\allFile\\01 temp\\1.txt";  
    String targetPath = "F:\\allFile\\01 temp\\2.txt";  
  
    try (  
            FileReader fileReader = new FileReader(srcPath);  
            FileWriter fileWriter = new FileWriter(targetPath);  
  
            BufferedReader bufferedReader = new BufferedReader(fileReader);  
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);  
    ) {  
        String s = bufferedReader.readLine();  
        while (s != null) {  
            bufferedWriter.write(s);  
            bufferedWriter.newLine();  
            s = bufferedReader.readLine();  
        }  
    } catch (IOException e) {  
        throw new RuntimeException(e);  
    }  
}