前几节我们学习了文件字节输入输出流和文件字符输入输出流,这一节我们学习一个新的概念——缓冲流。那什么叫做缓冲流呢?缓冲流又能起到什么作用呢?


在Java中,我们把BufferedReaderBufferedWriter类创建的对象称为缓冲输入输出流,二者增强了读写文件的能力。比如,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


点赞(0)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)