前几节我们学习了文件字节输入输出流和文件字符输入输出流,这一节我们学习一个新的概念——缓冲流。那什么叫做缓冲流呢?缓冲流又能起到什么作用呢?
在Java中,我们把BufferedReader和BufferedWriter类创建的对象称为缓冲输入输出流,二者增强了读写文件的能力。比如,Sudent.txt是一个学生名单,每个姓名占一行。如果我们想读取名字,那么每次必须读取一行,使用FileReader流很难完成这样的任务,因为,我们不清楚一行有多少个字符,FileReader类没有提供读取一行的方法。
Java提供了更高级的流:BufferedReader流和BufferedWriter流,二者的源和目的地必须是字符输入流和字符输出流。因此,如果把文件字符输入流作为BufferedReader流的源,把文件字符输出流作为BufferedWriter流的目的地,那么,BufferedReader和BufferedWriter类创建的流将比字符输入流和字符输出流有更强的读写能力。比如,BufferedReader流就可以按行读取文件。
BufferedReader类和BufferedWriter的构造方法分别是:
1 2 | BufferedReader(Reader in); BufferedWriter(Writer out); |
BufferedReader流能够读取文本行,方法是readLine()。通过向BufferedReader传递一个Reader子类的对象,比如FileReader的实例,来创建一个BufferedReader对象,例如:
1 2 | FileReader inOne = new FileReader( "Student.txt" ); BufferedReader inTwo = BufferedReader(inOne); |
然后inTwo流调用readLine()方法中读取Student.txt,例如:
1 | String strLine = inTwo.readLine(); |
类似地,可以将BufferedWriter流和FileWriter流连接在一起,然后使用BufferedWriter流将数据写到目的地,例如:
1 2 | FileWriter tofile = new FileWriter( "hello.txt" ); BufferedWriter out = BufferedWriter(tofile); |
然后out使用BufferedReader类的方法write(String s,int off,int len)把字符串s写到hello.txt中,参数off是s开始处的偏移量,len是写入的字符数量。
另外,BufferedWriter流有一个独特的向文件写入一个回行符的方法:
1 | newLine(); |
可以把BufferedReader和BufferedWriter称为上层流,把它们指向的字符流称为底层流,Java采用缓存技术将上层流和底层流连接。底层字符输入流首先将数据读入缓存,BufferedReader流再从缓存读取数据;BufferedWriter流将数据写入缓存,底层字符输出流会不断地将缓存中的数据写入到目的地。当BufferedWriter流调用flush()刷新缓存或调用close()方法关闭时,即使缓存没有溢出,底层流也会立刻将缓存的内容写入目的地。
注意:关闭输出流时要首先关闭缓冲输出流,然后关闭缓冲输出流指向的流,即先关闭上层流再关闭底层流。在编写代码时只需关闭上层流,那么上层流的底层流将自动关闭。
例如:
由英语句子构成的文件english.txt如下,每句占一行:
1 2 3 | The arrow missed the target. They rejected the union demand. Where does this road go to? |
要求按行读取english.txt,并在该行的后面加上该英语句子中含有的单词数目,然后再将该行写入到一个名字为englishCount.txt的文件中,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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+ "句子中单词个数:" +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()+ "内容:" ); while ((s=bufferRead.readLine()) != null ) { System.out.println(s); } bufferRead.close(); in.close(); } catch (IOException e) { System.out.println(e.toString()); } } } |
运行结果如下:
1 2 3 4 | englishCount.txt内容: The arrow missed the target.句子中单词个数: 5 They rejected the union demand.句子中单词个数: 5 Where does this road go to?句子中单词个数: 6 |
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程