首先,介绍一下文件处理流和文件节点流之间的区别和联系。
节点流 :从特定的数据源读取数据,例如:FileReader、FileWriter…
处理流(也叫包装流):是“连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如BufferedReader、BufferedWriter。
- 节点流是底层流/低级流,直接跟数据源相接.
- 处理流包装节点流,既可以消除不同节点流的现实差异,也可以提供更方便的方法来完成输入输出.
- 处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连。
下面是一些常见的节点流和包装流的类。
先说明一下IO流的主要分类,以访问文件为例:
读取流 | 输出流 | |
---|---|---|
字节流 | FileInputStream | FileOutputStream |
字符流 | FileReader | FileWriter |
我们拓展开来(不用死记硬背):
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
---|---|---|---|---|
抽象基类 | InputStream | OutputStream | Reader | Writer |
==下面是节点流 == | ||||
访问文件类 | FileInputStream | FileOutputSream | FileReader | FileWriter |
访问数组类 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
访问管道类 | PipedInputStream | PipedOutputStream | PipedReader | PiperWriter |
访问字符串 | StringReader | StringWriter | ||
==下面是处理流 == | ||||
缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
转换流 | InputStreamReader | OutputStreamWriter | ||
对象流 | ObjectInputStream | ObjectOutputStream | ||
抽象基类 | FilterInputStream | FilterOutputStream | FilterReader | FilterWriter |
打印流 | PrintStream | PrintWriter | ||
推回输入流 | PushbackInput | PushbackReader | ||
特殊流 | DataInputStream | DataOutputStream |
具体讲一讲修饰器模式在处理流的运用
我们打开BufferedReader的源码图。
我们发现,在BufferedReader的构造器上,要传入一个Reader的类,这个类可以是任何Reader的实现子类。在BufferedReader类中维护着一个Reader属性,这样就可以将一些操作进一步提升封装性,以提升可操作性。同属于第一张表格中某一类的节点流,都可以被这一类的处理流包装。例如:同属于Reader这一类的节点流,那么都可以被BufferedReader所包装.
还是不清楚?下面我们来手动模仿一下修饰者模式.
1.首先创建一个抽象基类
public abstract class Reader_ {
//设置两个抽象方法,让其子类实现
public void readFile(){
}
public void readChar(){
}
}
2.随后,创建两个它的实现子类,相当于FileReader和CharReader
public class CharReader_ extends Reader_{
@Override
public void readChar() {
System.out.println("读取了字符");
}
}
public class FileReader_ extends Reader_{
@Override
public void readFile() {
System.out.println("读取了文件~~~");
}
}
3.然后我们创建一个处理流,里面有两个包装的方法,也有两个正常的方法
public class BufferReader_ extends Reader_{
private Reader_ in;
public BufferReader_(Reader_ in) {
this.in = in;
}
@Override
public void readChar() {
in.readChar();
}
public void readChar(int nums) {
for (int i = 0; i < nums; i++) {
in.readChar();
}
}
@Override
public void readFile() {
in.readFile();
}
public void readFile(int nums) {
for (int i = 0; i < nums; i++) {
in.readFile();
}
}
}
现在,让我们看一下类图
让我们来测试一下,处理流能否正常使用.
public class Test {
public static void main(String[] args) {
// 先试用文件读取,测试一下
FileReader_ fileReader = new FileReader_();
BufferReader_ bufferReader = new BufferReader_(fileReader);
bufferReader.readFile();// 读取一次
System.out.println("-------我是分割线-------");
bufferReader.readFile(5);// 读取五次
// 在用字符读取试一下
CharReader_ charReader = new CharReader_();
BufferReader_ bufferReader1 = new BufferReader_(charReader);
bufferReader1.readChar();// 读取一次
System.out.println("-------我是分割线-------");
bufferReader1.readChar(5);// 读取五次
}
}
结果是:
处理流的功能主要体现在以下两个方面:
1.性能的提高:主要以增加缓冲的方式来提高输入输出的效率。
2.操作的便捷:处理流可能提供了一系列便捷的方式来输入输出大批量的数据,使用更加灵活方便。
恭喜你看到了文章末尾~~~~