前几节我们学习了文件字节输入输出流和文件字符输入输出流,这一节我们学习一个新的概念——缓冲流。那什么叫做缓冲流呢?缓冲流又能起到什么作用呢?
在Java中,我们把BufferedReader和BufferedWriter类创建的对象称为缓冲输入输出流,二者增强了读写文件的能力。比如,Sudent.txt是一个学生名单,每个姓名占一行。如果我们想读取名字,那么每次必须读取一行,使用FileReader流很难完成这样的任务,因为,我们不清楚一行有多少个字符,FileReader类没有提供读取一行的方法。
Java提供了更高级的流:BufferedReader流和BufferedWriter流,二者的源和目的地必须是字符输入流和字符输出流。因此,如果把文件字符输入流作为BufferedReader流的源,把文件字符输出流作为BufferedWriter流的目的地,那么,BufferedReader和BufferedWriter类创建的流将比字符输入流和字符输出流有更强的读写能力。比如,BufferedReader流就可以按行读取文件。
BufferedReader类和BufferedWriter的构造方法分别是:
BufferedReader(Reader in); BufferedWriter(Writer out);
BufferedReader流能够读取文本行,方法是readLine()。通过向BufferedReader传递一个Reader子类的对象,比如FileReader的实例,来创建一个BufferedReader对象,例如:
FileReader inOne = new FileReader("Student.txt"); BufferedReader inTwo = BufferedReader(inOne);
然后inTwo流调用readLine()方法中读取Student.txt,例如:
String strLine = inTwo.readLine();
类似地,可以将BufferedWriter流和FileWriter流连接在一起,然后使用BufferedWriter流将数据写到目的地,例如:
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流有一个独特的向文件写入一个回行符的方法:
newLine();
可以把BufferedReader和BufferedWriter称为上层流,把它们指向的字符流称为底层流,Java采用缓存技术将上层流和底层流连接。底层字符输入流首先将数据读入缓存,BufferedReader流再从缓存读取数据;BufferedWriter流将数据写入缓存,底层字符输出流会不断地将缓存中的数据写入到目的地。当BufferedWriter流调用flush()刷新缓存或调用close()方法关闭时,即使缓存没有溢出,底层流也会立刻将缓存的内容写入目的地。
注意:关闭输出流时要首先关闭缓冲输出流,然后关闭缓冲输出流指向的流,即先关闭上层流再关闭底层流。在编写代码时只需关闭上层流,那么上层流的底层流将自动关闭。
例如:
由英语句子构成的文件english.txt如下,每句占一行:
The arrow missed the target. They rejected the union demand. Where does this road go to?
要求按行读取english.txt,并在该行的后面加上该英语句子中含有的单词数目,然后再将该行写入到一个名字为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+"句子中单词个数:"+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()); } } }
运行结果如下:
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、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程