IO是非常重要的一块,但通常又被人们所忽视,这里希望能有个很清晰的介绍。自己学习的同时希望能够给别人带来一些帮助,对文章中用到其他作者(已经给出了链接)的图片在这里表示感谢!

IO的分类

java IO可以分成两类: 
(1)基于字节操作的io接口:InputStream 和 OutputStream 
(2)基于字符操作的io接口:Writer 和 Reader 
不论是磁盘还是网络传输,他们的最小单位都是字节,但是程序中的数据大多都是以字符的形式呈现,所以java也提供了对字符流的支持。还有一点需要注意的是,数据的传输方式也很重要,即数据写到哪里的问题,一般是一下两种方式: 
1. 基于磁盘操作的io接口:File 
2. 基于网络操作的io接口:Socket

IO流的整体结构

java I/O总结_字符流 
图片引用自( 引用块内容

InputStream的类层次结构

java I/O总结_输出流_02

OutputStream的类层次结构

java I/O总结_构造方法_03

以上图片引用自(这里写链接内容

Reader和Writer类的层次关系

Reader是java IO中所有的Reader的基类。类似于InpuStream,不同点在于Reader是基于字符的,也就是Reader用于读取文本,而InpuStream用于读取原始的字节。

java中使用UTF8编码来表示字符串,这在字节流和字符流进行转换的时候需要注意。如果从输入流中一字节为单位读取UTF8编码的文本,并且尝试将读到的字节转换成字符,这个时候可能会出错!

Writer是java IO中的所有Writer的基类,同样Writer是基于字符而不是字节,用于写入文本。

java I/O总结_构造方法_04
图片引用自(这里写链接内容)

字节流和字符流的转换

数据的持久化和网络传输都是以字节的形式进行的,所以字节流和字符流之间必然存在转换的问题。转换分为两个方向:字节到字符的转换和字符到字节的转换。这里主要涉及到编码和解码的问题,举例来说,InputStream.read()方法在数据流中读取字节(read()每次都只读取一个字节,效率非常慢,我们一般都是使用read(byte[])),然后保存在一个byte[]数组中,最后转换为String。在我们读取文件时,读取字节的编码取决于文件所使用的编码格式,而在转换为String过程中也会涉及到编码的问题,如果两者之间的编码格式不同可能会出现问题。例如存在一个*.txt编码格式为UTF-8,那么通过字节流读取文件时所获得的数据流编码格式就是UTF-8,而我们在转化成String过程中如果不指定编码格式,则默认使用系统编码格式(GBK)来解码操作,由于两者编码格式不一致,那么在构造String过程肯定会产生乱码。

字节转换成字符的桥梁是InputStreamReader,他使用指定的charset读取字节并将其解码为字符。我们既可以指定编码方式也可以接受平台的默认字符集。

基类InputStream和其实现类

图片引用自(这里写链接内容
java I/O总结_输出流_05

构造方法: 
InputStream() 创建一个输入的stream流 
其他方法 
1. close():关闭stream方法,这个是每次在用完流之后必须调用的方法。 
2. read():方法是读取一个byte字节,但是返回的是int。 
3. read(byte[]):一次性读取内容到缓冲字节数组 
4. read(byte[],int,int):从数据流中的哪个位置offset开始读长度为len的内容到缓冲字节数组 
5. skip(long):从stream中跳过long类型参数个位置

InputStream的实现类

@ByteArrayInputStream– 把内存中的一个缓冲区作为 InputStream 使用 .

构造方法 
(A)ByteArrayInputStream(byte[]) 创建一个新字节数组输入流( ByteArrayInputStream ),它从指定字节数组中读取数据(使用byte作为缓冲区数组) 
(B)ByteArrayInputStream(byte[], int, int) 创建一个新字节数组输入流,它从指定字节数组中读取数据。 
举例: 
byte[] buff = new byte[] { 2, 15, 67, -1, -9, 9 }; 
ByteArrayInputStream in = new ByteArrayInputStream(buff, 1, 4);

@StringBufferInputStream – 把一个 String 对象作为 InputStream .

构造方法 
StringBufferInputStream(String) 据指定串创建一个读取数据的输入流串。

@ FileInputStream – 把一个文件作为 InputStream ,实现对文件的读取操作

构造方法 
(A)FileInputStream(File name) 创建一个输入文件流,从指定的 File 对象读取数据。 
(B)FileInputStream(FileDescriptor) 创建一个输入文件流,从指定的文件描述器读取数据。 
(C)-FileInputStream(String name) 创建一个输入文件流,从指定名称的文件读取数据。

@PipedInputStream :实现了 pipe 的概念,主要在线程中使用 . 管道输入流是指一个通讯管道的接收端。

构造方法 
(A)PipedInputStream() 创建一个管道输入流,它还未与一个管道输出流连接。 
(B)PipedInputStream(PipedOutputStream) 创建一个管道输入流 , 它已连接到一个管道输出流。

@ SequenceInputStream :把多个 InputStream 合并为一个 InputStream . “序列输入流”类允许应用程序把几个输入流连续地合并起来并且使它们像单个输入流一样出现。每个输入流依次被读取,直到到达该流的末尾。然后“序列输入流”类关闭这个流并自动地切换到下一个输入流。

构造方法 
SequenceInputStream(Enumeration) 创建一个新的序列输入流,并用指定的输入流的枚举值初始化它。 
SequenceInputStream(InputStream, InputStream) 创建一个新的序列输入流,初始化为首先 读输入流 s1, 然后读输入流 s2 。

@ObjectInputStream:用于操作Object的stream,这个在stream主要用在对象传输的过程中,其中牵涉到了序列化的知识

构造方法 
ObjectInputStream():实例化一个ObjectInputStream对象 
ObjectInputStream(InputStream):使用一个InputStream对象来实例化一个ObjectInputStream对象,其中InputStream就是对象的输入流

@ FilterInputStream:是一个过滤的InputStream

构造方法 
FilterInputStream(InputStream):使用一个InputStream为参数实例化一个FilterInputStream,这是一个装饰者模式,从他子类的构造方法就可以看出端倪。他拥有子类如下:

1)BufferedInputStream:使用缓冲区的stream 
构造方法 
BufferedInputStream(InputStream):使用InputStream为参数初始化实例 
BufferedInputStream(InputStream,int):能够设置缓冲区大小的BufferedInputStream

2)DataInputStream:数字格式化的stream 
构造方法 
DataInputStream(InputStream):使用InputStream参数来初始化实例

基类OutputStream

OutputStream 
构造方法 
OutputStream() 
其他方法 
1. write(int):写入一个字节到stream中 
2. write(byte[])写入一个byte数组到stream中 
3. write(byte[],int,int):把byte数组中从offset开始处写入长度为len的数据 
4. close():关闭流,这个是在操作完stream之后必须要调用的方法 
5. flush():这个方法是用来刷新stream中的数据,让缓冲区中的数据强制的输出 
继承的子类如下:

@ByteArrayOutputStream : 把信息存入内存中的一个缓冲区中 . 该类实现一个以字节数组形式写入数据的输出流。

构造方法 
(A)— ByteArrayOutputStream() 创建一个新的字节数组输出流。 
(B)— ByteArrayOutputStream() 创建一个新的字节数组输出流。 
(C)— ByteArrayOutputStream(int) 创建一个新的字节数组输出流,并带有指定大小字节的缓冲区容量。

@ FileOutputStream: 文件输出流是向 File 或 FileDescriptor 输出数据的一个输出流

构造方法 
(A)FileOutputStream(File name) 创建一个文件输出流,向指定的 File 对象输出数据。 
(B)FileOutputStream(FileDescriptor) 创建一个文件输出流,向指定的文件描述器输出数据。 
(C)FileOutputStream(String name) 创建一个文件输出流,向指定名称的文件输出数据。 
(D)FileOutputStream(String, boolean) 用指定系统的文件名,创建一个输出文件。

@ PipedOutputStream: 管道输出流是指一个通讯管道的发送端。 一个线程通过管道输出流发送数据, 
而另一个线程通过管道输入流读取数据,这样可实现两个线程间的通讯。

构造方法 
(A)PipedOutputStream() 创建一个管道输出流,它还未与一个管道输入流连接。 
(B)PipedOutputStream(PipedInputStream) 创建一个管道输出流,它已连接到一个管道输入流。

@ObjectOutputStream:输出Object对象的stream

构造方法 
ObjectOutputStream:实例化一个ObjectOutputStream对象 
ObjectOutputStream(OutputStream):使用OutputStream对象来实例化一个ObjectOutputStream对象,将对象写入到OutputStream中

@FilterOutputStream:过滤的OutputStream,下面几个是他的子类

构造方法 
FilterOutputStream(OutputStream):使用OutputStream参数实例化FilterOutputStream

@BufferedOutputStream:带有缓冲区的stream

构造方法 
BufferedOutputStream(OutputStream):使用OutputStream参数初始化BufferedOutputStream类 
BufferedOutputStream(OutputStream,int):在初始化实例的时候指定缓冲区的大小

@ DataOutputStream:具有格式化的OutputStream

构造方法 
DataOutputStream(OutputStream):使用OutputStream参数来初始化DataOutputStream实例

@PrintStream:直接输出到控制台中:我们最熟悉的就是System.out他就是一个PrintStream

构造方法 
PrintStream(OutputStream):使用OutputStream参数来实例化PrintStream

字符流Stream——Reader和Writer

Reader基类:基于字符流的stream 
构造函数 
Reader():无参的构造方法

@CharArrayReader :与 ByteArrayInputStream 对应此类实现一个可用作字符输入流的字符缓冲区 
构造函数 
CharArrayReader(char[]) 用指定字符数组创建一个 CharArrayReader 。 
CharArrayReader(char[], int, int) 用指定字符数组创建一个 CharArrayReader

@ StringReader : 与 StringBufferInputStream 对应其源为一个字符串的字符流。

@ FileReader : 与 FileInputStream 对应

@ PipedReader :与 PipedInputStream 对应

@ InputStreamReader:将InputStream转化成Reader

基类Writer

@CharArrayWriter: 与 ByteArrayOutputStream 对应

@ StringWriter:无与之对应的以字节为导向的 stream

@ FileWriter: 与 FileOutputStream 对应

@ PipedWriter:与 PipedOutputStream 对应

@ OutputStreamWriter:将OutputStream转化成Writer

@ PrintReader:和PrintStream对应

字节流和字符流Stream 之间的转换 
@ InputStreamReader 和 OutputStreamReader : 
把一个以字节为导向的 stream 转换成一个以字符为导向的 stream 。 
InputStreamReader 类是从字节流到字符流的桥梁:它读入字节,并根据指定的编码方式,将之转换为字符流。 
使用的编码方式可能由名称指定,或平台可接受的缺省编码方式。 
InputStreamReader 的 read() 方法之一的每次调用,可能促使从基本字节输入流中读取一个或多个字节。 
为了达到更高效率,考虑用 BufferedReader 封装 InputStreamReader , 
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));