I/O问题是整个人机交互的核心问题,同样Java提供了丰富的操作I/O的类,此处只讨论java.io包中的63个类(除去Exception类和Error类),根据数据格式和传输方式可以分成四类(平时可能使用最多的是字节流和字符流):
(1)基于字节操作的I/O接口:InputStream和OutputStream (2)基于字符操作的I/O接口:Reader和Writer (3)基于磁盘操作的I/O接口:File (4)基于网络操作的I/O接口:Socket
基于字节操作的I/O接口输入和输出分别是InputStream和OutputStream,InputStream的类层次结构如下所示(输入流根据数据类型和操作方式又被划分为若干个子类): InputStream提供的主要方法:
public int read(byte b[], int off, int len) throws IOException;OutputStream的类层次结构与InputStream的结构类似:
public void write(byte b[], int off, int len) throws IOException;至于每个子类的具体操作方式和处理字节流的方式参考jdk1.8文档。
在实际的磁盘操作或是网络操作中,操作的都是字节,而并不是字符,之所以有字符流之说是因为在实际程序中经常使用字符或者字符串,为了操作方便提供字符I/O接口。而不同的字符使用的编码不尽相同,这给在转换成字节时如果使用了不恰当的解码规则就会产生乱码,同时编解码本身也是一个耗时的操作。 基于字符操作的I/O接口输入和输出分别是Reader和Writer,Reader的类层次结构如下所示: Reader提供的主要方法:
/** * Reads characters into a portion of an array. This method will block * until some input is available, an I/O error occurs, or the end of the * stream is reached. * * @param cbuf Destination buffer * @param off Offset at which to start storing characters * @param len Maximum number of characters to read * @return The number of characters read, or -1 if the end of the * stream has been reached * * @exception IOException If an I/O error occurs */ abstract public int read(char cbuf[], int off, int len) throws IOException;Writer的类层次结构与Reader的结构类似: Writer提供的主要方法:
/** * Writes a portion of an array of characters. * * @param cbuf Array of characters * @param off Offset from which to start writing characters * @param len Number of characters to write * @throws IOException If an I/O error occurs */ abstract public void write(char cbuf[], int off, int len) throws IOException;数据持久化到磁盘或者在网络上传输的时候都是以字节形式处理的,Java针对字节与字符的转化提供了相应的接口:InputStreamReader和InputStreamWriter。InputStreamReader将字节流解码成字符,InputStreamWriter将字节流编码成字符,不管编码解码均须注意采用的字符集,两种转换均采用了适配器模式(通过InputStreamReader或者InputStreamWriter将InputStream适配成Reader或者Writer)。 字符解码过程(在StreamDecode中存在InputStream和Charset对象用于转化):
字符编码过程(StreamEncoder中存在OutputStream和Charset对象用于转化):