下面是我近一段时间,复习IO流的一些知识点:
一.分类:
1. 按流向分类:
输入流:程序可以从中读取数据的流;
如:InputStream/Reader
输出流:程序可以向其写入数据的流;
如:OutputStream/Writer
2.按数据传输单位分类:
字节流:以字节(8位二进制)为单位进行处理。主要用于读写诸如图像或声音的二进制数据。
如:FileInputStream/FileOutputStream
字符流:以字符(16位二进制)为单位进行处理。主要用于读写诸如文本文件的数据。
如:FileReader/FileWriter
注意:字符流可以看做是一种包装流,因为在字符流源码中底层还是通过字节流进行读写操作。
3.按功能分类:
节点流:直接与原始数据存在的特定介质(如磁盘文件或其他外部设备、内存某区域)打交道的流。
如:FileInputStream/FileOutputStream/FileReader/FileWriter
过滤流:使用其它的流作为输入源或输出目的地,对流中的数据提供进一步处理的流。其他的流可以是节点流,
也可以是另一种过滤流。
例如:BufferedInputStream/DataInputStream
注意:过滤流必须建立在节点流之上,过滤流不能单独使用,一个输入流链或输出流链中一定有且只有一个节点流;可以没有,
也可以有多个过滤流。
二. IO流概略图:
三.过滤流:
说白了,过滤流就是不能直接与目标打交道,比如说:如磁盘文件或其他外部设备、内存某区域; 那 反之 节点流是能直接与目标打交道的;
FilterOutputStream(OutputStream out) : 此类是过滤输出流的所有类的超类(父类)
需要传入一个OutputStream。
在InputStream和OutputStream的子类中,FilterInputStream和FilterOutputStream是过滤流,
其又派生出子类DataInputStream和DataOutputStream数据输入流和数据输出流。
过滤流的主要特点是对节点流中的数据进行某些加工、处理,并提供一些友好的方法供用户进行输入、输出操作以及流控制,
例如,DataInputStream和DataOutputStream可 以读写Java基本数据类型的数据,方便读写操作。
BufferedInputStream可以对任何种类的输入流进行带缓冲区的封装,以达到性能的改善(可减少程序I/O操作次数,提高程序执行效率)。
Java利用过滤流可以在读/写数据的同时对数据进行处理。
使用过滤流时要注意:必须将过滤流和某个输入流或输出流(节点流)连接,而在程序设计中,连接是通过在过滤流的构造方法中指定的参数(节点流)
来实现的,多数利用 FileInputStream或FileOutputStream的对象作节点流参数,
如:
FileInputStream in=new FileInputStream("data.txt");
DataInputStream dfin=new DataInputStream (in);
实现了过滤流dfin和文件输入流in连接。在读写数据时,我们应该使用过滤流链中的最后一个过滤流进行实际的读写操作。
解释一下:过滤流链 -- 当多个过滤流链接在一起时,就形成了过滤流链;(其实,在设计模式中是: “装饰模式”)
四. 字符流与字节流的转换:
前几天,碰到一个问题,就是字符流与字节流的转换,结果吃了大亏,查看了一下源码才发现其中的秘密!
JDK 1.6中解释:
- InputStreamReader:字节到字符的桥梁
- OutputStreamWriter:字符到字节的桥梁
InputStreamReader: 是Reader的最重要的具体子类,InputStreamReader从其底层字节输入流(如FileInputStream)中读取字节,
根据指定的编码方式(字符集编码)将这些字节转换为字符,并返回这些字符。我们可以在构造函数中指定要读取的字节输入流和所用的编码方式:
InputStreamReader(InputStream in)
:创建一个使用默认字符集的 InputStreamReader。
InputStreamReader(InputStream in,String charsetName)
: 创建使用指定字符集的 InputStreamReader。
OutputStreamWriter:是Writer的最重要的具体子类,OutputStreamWriter会接收需要输出的字符。它根据指定的编码方式(字符编码)
将这些字符转换为字节,然后调用底层字节输出流输出。它的构造函数指明了字符输出流和使用的编码方式:
OutputStreamWriter(OutputStream out)
:创建使用默认字符编码的 OutputStreamWriter。
OutputStreamWriter(OutputStream out,String charsetName)
:创建使用指定字符集的 OutputStreamWriter。
何时使用转换流:
- 当字节和字符之间有转换动作时;
- 流操作的数据需要编码或解码时。
五. InputStream与OutputStream要掌握的问题:
我们打开InputStream与OutputStream发现:
(1) 类 InputStream:
abstract int read() 从输入流中读取数据的下一个字节。 int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。 int read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。 |
(2)类 OutputStream:
void write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。 void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。 abstract void write(int b) 将指定的字节写入此输出流。 |
总结:由此我们看以看出来,InputStream与OutputStream都有一个抽象方法,我以OutputStream为例,
打开源代码发现,write(byte abyte0[]) 内部就是调用的write(byte[] b, int off, int len),
而write(byte[] b, int off, int len)内部是调用的write(int i),所以InputStream与OutputStream 调用的最底层方法
分别应该是read()、write(int b),而这两个最重要的底层方法又都是抽象方法,这样继承InputStream与OutputStream
的子类都必须提供read()、write(int b)的实现,从而造成的后果就是每个子类的实现方式都不一样。
好了,先总结这么多吧!如果我写的有不对的地方,欢迎大家即使的指正 --- 大饼