IO 是指 Input/Output,即输入和输出。以内存为中心:
Input指从外部读入数据到内存。例如:把文件从磁盘读取到内存,从网络中读取数据到内存Output指把数据从内存输出到外部。例如:把数据写入到磁盘中,把数据从内存输出到网络中
IO 流是一种顺序读写数据的模式,它的特点是单向流动。数据类似自来水一样在水管中流动,所以我们把它称为 IO 流。按照输入和输出,IO 流分为输入、输出两种 IO 流,每种输入、输出流又分为字节流和字符流两大类。
- 字节流以字节
byte为单位处理输入、输出操作 - 字符流以字符
char为单位处理输入、输出操作InputStream/OutputStream 字节流
从磁盘读入一个文件,包含 6 个字节,就相当于读入了 6 个字节的数据,读取过程是按顺序进行的称为输入字节流
反过来,把 6 个字节从内存写入磁盘文件中则称为输出字节流╔════════════╗║ Memory ║╚════════════╝▲│0x48│0x65│0x6c│0x6c│0x6f│0x21╔═══════════╗║ Hard Disk ║╚═══════════╝
╔════════════╗║ Memory ║╚════════════╝│0x21│0x6f│0x6c│0x6c│0x65│0x48▼╔═══════════╗║ Hard Disk ║╚═══════════╝
在
Java中,InputStream是所有输入字节流的基类,OutputStream是所有输出字节流的基类
Reader/Writer 字符流
把 char[] 数组 Hi你好 这 4 个字符用 Writer 字符流写入文件,并且使用 UTF-8 编码,得到的最终文件是 8 个字节,英文字符 H 和 i 各占一个字节,中文 你好 各占 3 个字节:
0x480x690xe4bda00xe5a5bd
反过来,用 Reader 读取以 UTF-8 编码的这 8 个字节,得到 Hi你好 这 4 个字符。
上述整个过程,Reader 和 Writer 本质上是一个自动编解码的 InputStream 和 OutputStream。Reader 内部把读入的数据从 byte 转换为了 char
字节流和字符流的用法几乎完全一样,如何选择使用 Reader 和 InputStream 要取决于具体的使用场景。如果数据源不是文本使用 InputStream,反之则使用 Reader
java.io 包
java.io 包中涉及处理 IO 流的有 40+ 类,这些类看起来很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系,这 40+ 类都是从 InputStream/OutputStream、Reader/Writer 4个抽象基类中派生出来的
按操作方式分类结构图:
按操作对象分类结构图:
BIO、NIO 和 AIO 之间的区别
BIO
BIO 指 Blocking I/O 全称同步阻塞 I/O 模型。此模型下数据的读取和写入必须阻塞在一个线程内等待其完成。这种适用于活动连接数不是特别高(小于单机 1000)的应用场景,可以让每一个连接专注于自己的 I/O 并且编码相对简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的
NIO
NIO 指 Non-blocking/New I/O 全称同步非阻塞 I/O 模型。非阻塞模型的应用场景与阻塞模型应用场景相反,它适用于高负载、高并发的(网络)应用。Java 1.4 引入了 NIO 框架,对应 java.nio 包,框架提供了 Channel,Selector,Buffer 等抽象,它支持面向缓冲的,基于通道的 I/O 操作方法
AIO
AIO 指 Asynchronous I/O 全称异步非阻塞 I/O 模型。AIO 与 BIO 和 NIO 完全不同,它是一种全新的设计。AIO 是基于事件和回调机制实现的,程序执行代码之后会直接返回,不会造成阻塞,当后台处理完成后,操作系统在通知相应的线程进行后续的操作。Java 7 中引入了 AIO
