1.5 Writer及其Family
Writer提供的方法和OutputStream提供的几乎是一样的,不同之处在于Writer的操作多数是char类型的,类结构如下图所示:
对比前面的Reader的类结构图,Java I/O在用时易混淆,给大家看个表,如下:
· 字节与字节的主要区别是:字节和字符都是二进制的数据,但是这种数据包含有区域信息(字符集), 需要翻译才可以获取实际的信息。
· 输入流与输出流的主要区别是:输入流的主要作用是从流中读取数据,输出(到)流的主要作用是向流中写入数据;
给大家一条好建议:把InputStream、OutputStream、Reader、Writer的类图分别打印出来,在自己模糊的时候拿出来看下,时间长了你就清楚了。人的记忆就是需要不断的加深再加深,这样你回忆的速度会越来越快。
1.6 RandomAccessFile及Serializable
前面总结了那么多,我在准备完成 Java I/O总结系列文章的时候,还是发现文章中遗漏了不少内容,本篇幅把这些遗漏的内容补充说明。
RandomAccessFile
前面对文件的读写都是流的顺序数据读写,实际文件的操作却往往会从文件的某个的特定位置开始读写操作,因而之前这些居于流思想的I/O类无法满足需求。RandomAccseeFile实现了任意位置读写的功能,此外还实现了DataInput、DataOutput接口,支持字节数据,字符数据和 Java基本数据类型的读写,类结构如下图所示:
其接口,我们在这里就不详细介绍了,需要强调说的是其构造函数,需要我们去仔细阅读,如下图所示:
看了上面的介绍,下面我们列举一个具体的例子,如下:
对象的可串行化
实现了DataInputStream和OutputStream接口的类可以做到对Java基本类型数据的读写,有事我们会遇到需要将程序运行过程中的某个对象保存下来,下次程序运行时通过读入保存的数据,可以恢复这个对象。
由于对象是运行期的产物,因此对对象的读写需要JVM的底层支持,这在Java中称做对象的串行化,一个可串行化的对象可以被存储成特定形式的二进制数据。将对象串行化也非常简单,只需要类实现 java.io.Serializable接口即可。这个接口没有定义任何的方法,仅仅用来表示实现这个接口的类的对象是可串行化,列举一个具体的例子,如下:
在这里需要强调说的是:
在一些特殊情况下,比如说数据存储时需要加密,这个时候需要自己实现Externalizable接口,这个接口如下图所示:
这个接口的实现非常简单,具体的实例就不列举了。
PipedInputStream和PipedOutputStream
在Window中可以使用Pipe实现数据传递,在Android中也有类似的方法:2个线程之间通过Pipe交换数据,PipedInputStream向管道中读取数据,PipedOutputStream读取管道的数据。下面我们来看这2个类的结构图,如下图所示:
下面我们列举一个具体的例子,如下: