BufferedReader和BufferedWriter出现的目的是为了对FileReader以及FileWriter的读写操作进行增强,而怎么增强呢,原理类似于使用StringBuilder,是把数据先放入他们的一个char数组中,然后再操作char数组。
使用缓冲区的字符流是使用了装饰着模式对FileReader等进行功能上的增强,装饰者模式与继承都可以实现功能上的增强,但是装饰者可以做得更加的灵活,也不会使继承树变得太过复杂。
以下是BufferedWriter源码的一小部分
public class BufferedReader extends Reader { private Reader in; 构造函数需要用到的Reader private char cb[]; 自己的char数组,它本身的read()方法将是访问这个数组,这个数组就是缓冲区 private int nChars, nextChar; char数组位置和数量的索引
接下来看一下BufferedWriter源码的read()方法:
public int read() throws IOException { synchronized (lock) { ensureOpen(); for (;;) { if (nextChar >= nChars) { fill(); if (nextChar >= nChars) return -1; } if (skipLF) { skipLF = false; if (cb[nextChar] == ‘\n‘) { nextChar++; continue; } } return cb[nextChar++]; } } }
这个read()方法是访问的BufferedReader本身的char数组,当发现数组的元素已经被访问完毕就调用fill()方法重新填充char数组。这个就是使用缓冲区的字符流的实质。
同样的,BufferedWriter也是先把数据写入自身的char数组中,刷新的时候再写入文件。
注意:
1、当使用BufferedWriter或者是BufferedReader的时候,是把FileReader的赋给了BufferedReader里面的Reader对象,所以要保存数据到文件的时候调用传入BufferedReader的参数Reader是无效的,需要使用BufferedReader进行刷新或者关BufferedReader之后数据才会保存到文件;
2、当关闭BufferedReader的时候,传入作为参数的reader也会跟着关闭。
3、BufferedReader具有一个特殊的方法readerLine(),功能是读取一行,原理是从char数组中读取,判断是否遇到换行符,是的话返回。
下面有根据传智播客的IO视频自己写的一个BufferedReader代码:
public class MyBufferedReader { private Reader reader; private int count; private int position; private char[] contentArray = new char[1024]; private int ch; private final String LINE_SEPARATE = System.getProperty("line.separate"); public MyBufferedReader(Reader reader) { this.reader = reader; } public int myReader() throws IOException { if (count == 0) { count = reader.read(contentArray); position = 0; } if (count == -1) { return -1; } count--; ch = contentArray[position]; position++; return ch; } public String myReadLine() throws IOException { StringBuilder sb = new StringBuilder(256); int ch = 0; while ((ch = myReader()) != -1) { if (ch == ‘\r‘) { continue; } if ((char) ch == ‘\n‘) { return sb.toString(); } sb.append((char) ch); } if (sb.length() > 0) return sb.toString(); return null; } public void close() throws IOException { reader.close(); } }
这里是调用的代码:
try (FileWriter fileWriter = new FileWriter("buffer.txt")) { try (BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) { int count = 3; while (count != 0) { bufferedWriter.write("123456"); bufferedWriter.newLine(); bufferedWriter.write("abcdef"); bufferedWriter.newLine(); count--; } } } try (FileReader fileReader = new FileReader("buffer.txt")) { MyBufferedReader bufferedReader = new MyBufferedReader(fileReader); String line = null; while ((line = bufferedReader.myReadLine()) != null) { System.out.println(line); } }
运行结果为:
Disconnected from the target VM, address: ‘127.0.0.1:26416‘, transport: ‘socket‘ 123456 abcdef 123456 abcdef 123456 abcdef Process finished with exit code 0