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