前幾節(jié)我們學(xué)習(xí)了文件字節(jié)輸入輸出流和文件字符輸入輸出流,這一節(jié)我們學(xué)習(xí)一個(gè)新的概念——緩沖流。那什么叫做緩沖流呢?緩沖流又能起到什么作用呢?
在Java中,我們把BufferedReader和BufferedWriter類(lèi)創(chuàng)建的對(duì)象稱(chēng)為緩沖輸入輸出流,二者增強(qiáng)了讀寫(xiě)文件的能力。比如,Sudent.txt是一個(gè)學(xué)生名單,每個(gè)姓名占一行。如果我們想讀取名字,那么每次必須讀取一行,使用FileReader流很難完成這樣的任務(wù),因?yàn)?,我們不清楚一行有多少個(gè)字符,F(xiàn)ileReader類(lèi)沒(méi)有提供讀取一行的方法。
Java提供了更高級(jí)的流:BufferedReader流和BufferedWriter流,二者的源和目的地必須是字符輸入流和字符輸出流。因此,如果把文件字符輸入流作為BufferedReader流的源,把文件字符輸出流作為BufferedWriter流的目的地,那么,BufferedReader和BufferedWriter類(lèi)創(chuàng)建的流將比字符輸入流和字符輸出流有更強(qiáng)的讀寫(xiě)能力。比如,BufferedReader流就可以按行讀取文件。
BufferedReader類(lèi)和BufferedWriter的構(gòu)造方法分別是:
BufferedReader(Reader in); BufferedWriter(Writer out);
BufferedReader流能夠讀取文本行,方法是readLine()。通過(guò)向BufferedReader傳遞一個(gè)Reader子類(lèi)的對(duì)象,比如FileReader的實(shí)例,來(lái)創(chuàng)建一個(gè)BufferedReader對(duì)象,例如:
FileReader inOne = new FileReader("Student.txt"); BufferedReader inTwo = BufferedReader(inOne);
然后inTwo流調(diào)用readLine()方法中讀取Student.txt,例如:
String strLine = inTwo.readLine();
類(lèi)似地,可以將BufferedWriter流和FileWriter流連接在一起,然后使用BufferedWriter流將數(shù)據(jù)寫(xiě)到目的地,例如:
FileWriter tofile = new FileWriter("hello.txt"); BufferedWriter out = BufferedWriter(tofile);
然后out使用BufferedReader類(lèi)的方法write(String s,int off,int len)把字符串s寫(xiě)到hello.txt中,參數(shù)off是s開(kāi)始處的偏移量,len是寫(xiě)入的字符數(shù)量。
另外,BufferedWriter流有一個(gè)獨(dú)特的向文件寫(xiě)入一個(gè)回行符的方法:
newLine();
可以把BufferedReader和BufferedWriter稱(chēng)為上層流,把它們指向的字符流稱(chēng)為底層流,Java采用緩存技術(shù)將上層流和底層流連接。底層字符輸入流首先將數(shù)據(jù)讀入緩存,BufferedReader流再?gòu)木彺孀x取數(shù)據(jù);BufferedWriter流將數(shù)據(jù)寫(xiě)入緩存,底層字符輸出流會(huì)不斷地將緩存中的數(shù)據(jù)寫(xiě)入到目的地。當(dāng)BufferedWriter流調(diào)用flush()刷新緩存或調(diào)用close()方法關(guān)閉時(shí),即使緩存沒(méi)有溢出,底層流也會(huì)立刻將緩存的內(nèi)容寫(xiě)入目的地。
注意:關(guān)閉輸出流時(shí)要首先關(guān)閉緩沖輸出流,然后關(guān)閉緩沖輸出流指向的流,即先關(guān)閉上層流再關(guān)閉底層流。在編寫(xiě)代碼時(shí)只需關(guān)閉上層流,那么上層流的底層流將自動(dòng)關(guān)閉。
例如:
由英語(yǔ)句子構(gòu)成的文件english.txt如下,每句占一行:
The arrow missed the target. They rejected the union demand. Where does this road go to?
要求按行讀取english.txt,并在該行的后面加上該英語(yǔ)句子中含有的單詞數(shù)目,然后再將該行寫(xiě)入到一個(gè)名字為englishCount.txt的文件中,代碼如下:
import java.io.*; import java.util.*; public class Main { public static void main(String args[]) { File fRead = new File("english.txt"); File fWrite = new File("englishCount.txt"); try { Writer out = new FileWriter(fWrite); BufferedWriter bufferWrite = new BufferedWriter(out); Reader in = new FileReader(fRead); BufferedReader bufferRead = new BufferedReader(in); String str = null; while((str = bufferRead.readLine()) !=null) { StringTokenizer fenxi = new StringTokenizer(str); int count = fenxi.countTokens(); str = str+"句子中單詞個(gè)數(shù):"+count; bufferWrite.write(str); bufferWrite.newLine(); } bufferWrite.close(); out.close(); in = new FileReader(fWrite); bufferRead = new BufferedReader(in); String s = null; System.out.println(fWrite.getName()+"內(nèi)容:"); while((s=bufferRead.readLine()) !=null) { System.out.println(s); } bufferRead.close(); in.close(); } catch(IOException e) { System.out.println(e.toString()); } } }
運(yùn)行結(jié)果如下:
englishCount.txt內(nèi)容: The arrow missed the target.句子中單詞個(gè)數(shù):5 They rejected the union demand.句子中單詞個(gè)數(shù):5 Where does this road go to?句子中單詞個(gè)數(shù):6
C語(yǔ)言網(wǎng)提供由在職研發(fā)工程師或ACM藍(lán)橋杯競(jìng)賽優(yōu)秀選手錄制的視頻教程,并配有習(xí)題和答疑,點(diǎn)擊了解:
一點(diǎn)編程也不會(huì)寫(xiě)的:零基礎(chǔ)C語(yǔ)言學(xué)練課程
解決困擾你多年的C語(yǔ)言疑難雜癥特性的C語(yǔ)言進(jìn)階課程
從零到寫(xiě)出一個(gè)爬蟲(chóng)的Python編程課程
只會(huì)語(yǔ)法寫(xiě)不出代碼?手把手帶你寫(xiě)100個(gè)編程真題的編程百練課程
信息學(xué)奧賽或C++選手的 必學(xué)C++課程
藍(lán)橋杯ACM、信息學(xué)奧賽的必學(xué)課程:算法競(jìng)賽課入門(mén)課程
手把手講解近五年真題的藍(lán)橋杯輔導(dǎo)課程