JAVA IO 流之字符流的缓冲区

1.缓冲区的出现提高了对数据的读写效率

2.对应类:

BufferedWriter
BufferedReader

缓冲区需要结合流才可以使用, 对流的功能进行了增强, 即对流的操作起到装饰作用

使用缓冲区实现文本文件的写入和读取

// 写入
public class BufferedWriterDemo{
    
    
    public static void main(String[] args) throws IOException {
    
    

        FileWriter fw = new FileWriter("buf.txt");

        // 为了提高写入的效率, 使用了字符流的缓冲区
        // 创建了一个字符写入流的缓冲对象, 并和指定要被缓冲的流对象相关联

        BufferedWriter bufw = new BufferedWriter(fw);

        // 使用缓冲区的写入方法将数据写入到缓冲区中
        bufw.write("abcde");

        // 换行, 其实就是封装了系统属性  line.separator
        // BufferedWriter 特有方法
        bufw.newLine();

        bufw.newline("hahaha");

        // 使用缓冲区的刷新方法将数据刷入到目的地中
        bufw.flush();

        // 关闭缓冲区, 其实关闭的就是被缓冲的流对象
        bufw.close();
    }//需要获取资料的朋友请加Q君样:290194256*
}

// 读取
public class BufferedReaderDemo {
    
    
    public static void main(String[] args){
    
    

        FileReader fr = new FileReader("buf.txt");
        BufferedReader bufr = new BufferedReader();

        /*  读取字符数组的方式
         *
         *  char[] buf = new char[1024];

         *  int len = 0;
         *  while((len=bufr.read(buf))!= -1){
    
    
         *  System.out.println(new String(buf,0,len));
         *  }
         */

         // 按一行读取, BufferredReader 特有方法: readLine()
         // 如果到达流末尾, 返回 null
         String line = null;
         while((line=bufr.readLine()) != null){
    
      // 注意: 此处判断的是 != null
            System.out.println(line);
        }//需要获取资料的朋友请加Q君样:290194256*

        // 关闭缓冲区
        bufr.close();
    }
}//需要获取资料的朋友请加Q君样:290194256*

BufferedReader 中的 readLine() 方法原理

BufferedReader 类复写了父类的以下方法:

read(); : 读取单个字符
read(char[] buf, int off, int len); : 读取数组的一部分
BufferedReader 类自己特有的方法 readLine()

BufferedReader 类继承了父类方法:

read(char[] buf) : 将字符读入数组

*eadLine() 方法原理:
在这里插入图片描述

使用了读取缓冲区的 read() 方法, 将读取到的字符进行缓冲并判断换行标记. 将标记前的缓存数据变成字符返回.

模拟实现 BufferedReader

// 需求: 自定义的读取缓冲区, 其实就是模拟一个 BufferedReader

/* 分析:
 *    缓冲区中无非就是封装了一个数组, 并对外提供了更多的方法对数组进行访问
 *    其实这些方法最终操作的都是数组的角标
 *
 *     缓冲区原理: 其实就是从源中获取一批数据装进缓冲区中, 在从缓冲区中不断
 *     的取出一个一个数据.
 *     
 *     在缓冲区中数据此次取完后, 在从源中继续取一批数据进缓冲区, 当源中的数据取光时,
 *     用 -1 作为结束标记
 */

 public class MyBufferedReader{
    
    

    private FileReader r;

    // 定义一个数组作为缓冲区
    private char[] buf = new char[1024];

    // 定义一个指针用于操作这个数组中的元素, 当操作到最后一个元素时, 指针应该归 0
    private int pos = 0;

    // 定义一个计数器, 记录缓冲区中的数据个数. 当该数据减到0, 就从源中继续获取数据到缓冲区中
    private int count = 0;

    // 带参数的构造函数, 指定增强的流对象
    public MyBufferedReader(FileReader r){
    
    
        this.r = r;
    }//需要获取资料的朋友请加Q君样:290194256*

    // 定义从缓冲区读取单个字符的 read() 方法
    public int myRead() throws IOException{
    
    

        // 1. 从源中获取一批数据到缓冲区中, 需要先做判断, 只有计数器为 0 时, 才需要从源中获取数据
        /* if(count == 0){
    
    

         *   // 记录从源中获取的数据个数
         *   count = r.read(buf);

         *   if(count < 0){
    
    
         *      return -1;
         *  }

         *  // 每次从源中获取数据到缓冲区后, 角标归零
         *   pos = 0;

         *   // 获取第一个数据
         *   char ch = buf[pos];

         *   pos++;
         *   count--;

         *   return ch;
         *   } else {
    
    

         *   char ch = buf[pos];

         *   pos++;
         *   count--;

         *   return ch;
         *   }
         */
        // 代码优化:

        if(count == 0){
    
    
            count = r.read(buf);

            pos = 0;
        }//需要获取资料的朋友请加Q君样:290194256*

        if(count < 0){
    
    
            return -1;
        }

        char ch = buf[pos++];

        count--;

        return ch;
    }

    // 定义从缓冲区读取一行字符的 readLine() 方法
    public String myReadLine() throws IOException{
    
    

        // 定义一个数组容器, 存储从缓冲区中获取到的数据
        StringBuilder sb = new StringBuilder();

        // 使用自定义的 MyRead 方法, 从缓冲区中不断获取单个字符,
        int ch = 0;
        while((ch=myRead()) != -1){
    
    

            if(ch=='\r')
                continue;
            if(ch=='\n')
                return sb.toString();

            // 将从缓冲区中读到的字符, 存储到缓存行数据的缓冲区中
            sb.append((char)ch);
        }

        // 如果最后一行结尾没有回车符, 缓冲区的读取已结束,
        // 但是并不能判断 if(ch=='\n'), 所有最后一行未能输出
        if(sb.length() != 0)
            return sb.toString();

        return null;
    }

    public void myClose() throws IOException{
    
    
        r.close();
    }

    }//需要获取资料的朋友请加Q君样:290194256*

使用缓冲区的方式复制文本文件

public class CopyTextByBufTest {
    
    
    public static void main(String[] args) throws IOException {
    
    
        FileReader fr = new FileReader("buf.txt");
        BufferedReader bufr = new BufferedReader(fr);

        FileWriter fw = new FileWriter("buf_copy.txt");
        BufferedWriter bufw = new BufferedWriter(fw);

        /*
         *  int ch = 0;
         *  // 使用缓冲区对象进行单个字符的读写
         *  // 这是直接从内存中读取单个字符, 不是从硬盘中
         *  while((ch=bufr.read()) != -1){
    
    
         *        bufw.write(ch);
         *    }
         */

         // 使用行进行读取文件

         String line = null;
         while((line=bufr.readLine())!=null){
    
    
            bufw.write(line);
            bufw.newLine();
            bufw.flush();  // 注意: 每次写入之后, 进行刷新保存
        }

        bufw.close();
        bufr.close();
}//需要获取资料的朋友请加Q君样:290194256*
}

LineNumberReader 装饰类

1.BufferedReader 的子类

2.可以跟踪行号的缓冲字符输入流

setLineNumber(int); : 设置当前行号
getLineNumber(); : 获取当前行号

在这里插入图片描述
在这里插入图片描述
最新2020整理收集的一些高频面试题(都整理成文档),有很多干货,包含mysql,netty,spring,线程,spring cloud、jvm、源码、算法等详细讲解,也有详细的学习规划图,面试题整理等,需要获取这些内容的朋友请加Q君样:290194256

猜你喜欢

转载自blog.csdn.net/weixin_53341657/article/details/113006984