因为前几天要写一个有关文件操作的程序,以前看的IO基本上都忘光了,所以又重新看了一遍,整理了点笔记。
数据流(stream)是一组有顺序的、有起点和终点的字节集合,是对输入和输出的总称和抽象。数据流分为输入流(InputStream)和输出流(OutputStream)。流通过Java的输入输出系统与物理设备连接。尽管与它们连接的物理设备不尽相同,但所有流的行为具有相同的方式。这样,相同的输入输出类和方法适用于所有类型的外部设备。这意味着一个输入流能够抽象多种不同类型的输入:从磁盘文件、从键盘、从线程管道和从网络套接字。同样,一个输出流可以输出到控制台、磁盘文件、线程管道或相连的网络。
流可以分为字节流和字符流。字节流是读写以单字节为基础的数据流,而读写以双字节的Unicode字符为基础的据流。InputStream和OutputStream是字节流的输入和输出的抽象类,Reader和Writer是字符流的输入和输出的抽象类。
基本字节流
InputStream和OutputStream
字节流抽象类,继承于它们又比较常用的类有FileInputStream和FileOutputStream,PipedInputStream和PipedOutputStream,FilterInputStream和FilterOutputStream。继承于FilterInputStream和FilterOutputStream 分别有BufferedInputStream、DataInputStream和BufferedOutputStream、DataOutputStream。
FileInputStream和FileOutputStream
节点流,用于从文件读取或往文件中写入字节流。如果在构造FileOutputStream时,文件已经存在,则覆盖这个文件。都可以采用File对象或文件名去构造,重写了InputStream中的三个read()方法和OutputStream中的三个write()方法。
BufferedInputStream和BufferedOutputStream
过滤流,需要使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的效率。BufferedInputStream真正实现了InputStream中的mark()和reset()方法,而BufferedInputStream真正实现了InputStream中的mark()和reset()方法,因为只有在缓冲区才能在流中标记当前位置。同理,BufferedOutputStream真正实现了flush()方法,在缓冲区的数据要强制写入磁盘时使用。
DataInputStream和DataOutputStream
过滤流,需要使用已经存在的节点流来构造,提供了读写Java中的基本数据类型的功能。
PipedInputStream和PipedOutputStream
管道流,用于线程间的通信。一个线程的PipedInputStream对象从另一个线程的PipedOutputStream对象读取输入。要使管道流有用必须同时构造管道输入流和管道输出流。
JavaI/O类库需要多种不同功能的组合,这就需要使用装饰模式。装饰模式是在不必改变原文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。如下面代码:
File f = new File(“test.txt”); //获取文件对象
FileInputStream fis = new FileInputStream(f); //构造文件输入流
BufferedInputStream bis = new BufferedInputStream(fis); //获得带缓冲的文件输入流
DataInputStream dis = new DataInputStream(bis); //取得带缓冲的写Java基本数据的文件流
尽管字节流提供了处理任何类型数据输入输出操作的足够的功能,但它们不能直接操作Unicode字符。而在Java虚拟机中,字符和字符串都是采用Unicode编码的,所以提供直接的字符输入输出支持是必要的,Reader和Writer这两个抽象类主要用来读写字符流。
Reader和Writer
字符类抽象类,继承于它们又比较常用的类有BufferedReader和BufferedWriter,InputStreamReader和OutputStreamWriter,FilterReader和FilterWriter,PipedReader和PipedWriter。
InputStreamReader和OutputStreamWriter
InputStreamReader 是字节流转化为字符流的类,相应地,OutputStreamWriter 是字符流转化为字节流的类。在Java虚拟机中,字符和字符串都是采用Unicode编码表示的,当我们去获取或构造字符或字符串就是一个解码的过程,如果是把字符或字符串转化为字节是一个编码的过程。所以,InputStreamReader是使用指定的字符集charset读取字节并将其解码为字符,而OutputStreamWriter是使用指定的字符集charset为将要写入的字符编码为字节。
RandomAccessFile
随机存取文件,对一个文件同时进行读写操作,可以在文件的任意位置进行读写操作。同时实现了DataInput和DataOutput接口,构造函数中要指定访问文件的模式,r表示读,w表示写,rw表示读写。该类提供了一个文件指针,用来标志要进行读写操作的下一数据的位置。
对象序列化
对象的寿命通常随着生成该对象的程序的终止而终止。但是在某些时候,需要将对象的状态保存下来,以便将来需要的时候可以恢复。对象的这种能记录自己的状态以便将来再生的能力,叫做对象的持续性。对象通过写出描述自己状态的数值来记录自己的过程,叫做对象的串行化。一个对象要想能够实现序列化,必须实现Serializable接口或Externalizable接口。
注意事项:
1.当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量。
2.如果一个对象的成员变量是另一个对象的引用,则引用的对象数据成员也会被序列化。这个过程是递归的,可能要涉及一个复杂树型结构的串行化,包括原有对象、对象中的对象等等。
3.对于一些需要保密的变量,为了保证安全性,不应该序列化的,可以在其前面加上transient关键字。
ObjectInputStream和ObjectOutputStream
ObjectInputStream继承了InputStream类并实现了ObjectInput接口,负责从流中读取对象。同样地,ObjectOutputStream继承了OutputStream类并实现了ObjectOutput接口,负责向流写入对象。