IO的概念
IO顾名思义,输入流(Input)和输出流(Output)的简称。IO问题也是当前Web应用中所面临的主要问题之一,因为在当前海量数据的时代,数据在网络中随处流动,在流动过程中都涉及IO的问题,可以说大部分Web应用系统的瓶颈都是IO瓶颈。在本文中主要从IO分类入手,简单介绍几种IO的特性以及工作机制,在这里NIO不做介绍,因为它内容之多,足以另外写一个帖子。
JDK中IO的接口分类
按照传输数据的数据格式,分为字节操作和字符操作。按照传输数据的方式,分为磁盘IO和网络IO,网络IO本质也是磁盘IO,只是需要其他一步处理,就是让底层操作系统将数据传输到其他地方而不是本地磁盘。
不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符。所以IO操作都是基于字节,而不是字符。之所以会有字符操作IO接口,是因为程序中常操作的数据都是字符形式,为了操作方便提供了一个直接操作字符的IO接口。从字符到字节要经过编码转换,并且容易出现让人头痛的乱码问题。
2.1 基于字节操作的IO接口: InputStream、OutputStream
输入流的层次结构图
输出流的层次结构图
每个类的作用 ?
Demo
OutputStream out = new BufferedOutputStream(new ObjectOutputStream(new FileOutputStream(“fileName”)));
//弄清楚这种组合最终想表达的是什么? 装饰器模式?
2.2 基于字符操作的IO接口: Writer 、Reader
Writer层次结构图
Reader层次结构图
每个类的作用 ?
Demo
2.3 基于磁盘操作的IO接口: File
2.4 基于网络操作的IO接口: Socket
2.5 字符和字节之间的转化接口
encode(编码):字符转成字节
decode(解码):字节转成字符
因为数据持久化或者网络传输都是以字节进行的,所以存在字符到字节和字节到字符的转化,也就是编码和解码方式。
InputStream是基于字节操作的IO接口,其中主要的方法是:
public int read(byte b[], int off, int len){
}
该方法的主要作用是,从输入的字节流中读取byte流,并且存入指定的b数组。
b: 指定存入的缓存字节数组
off:指定从缓存中存储的其实位置,并不一定是0。
len: 每次读取字节流中最大字节长度。
其中满足: (off + len )<=b.length; 不然会越界。
在操作字节的接口中,直接把字节流存入缓存的字节数组中。然后开发人员自己去进行解码操作,字节转成字符。一般使用String str = new String(byte[]);
但是在基于字符操作的接口中并不是这样。
Writer抽象类提供了写字符的操作借口是:
writer(char cbuff[], int off , int len) ;
Reader抽象类提供了读字符的操作接口是:
int read(char cbuff[], int off, int len);
从提供的接口中可以看出,并没有提供字符到字节或者字节到字符转换的接口。而是在writer()和read()都封装实现了编码或者解码。主要使用类是:StreamDecoder 和 StreamIncoder。
下面是使用FileReader读取文件的简易代码:
网络IO的工作机制
磁盘IO的工作机制
同步和异步
阻塞和非阻塞
IO的调优
IO中的设计模式
6.1 装饰器模式
6.2 适配器模式
简单介绍Apache 的 Commons IO 包的特性
参考文献:
1、JAVA学习笔记
2、深入浅出Java Web技术内幕