文章目录
  1. 1. 基于字节流的API: InputStream 和 OutputStream
  2. 2. 基于字符的API:Reader 和 Writer
  3. 3. 适配器API:InputStreamReader 和 OutputStreamWriter

时间飞逝,转眼就是2016,由于2015下半年事情太多,就把读书这事给松懈了,现在捡起来继续。

平时用java io主要是读写文件,网络传输方面基本不涉及。用java io API给我的最大感受就是读写一下文件,为啥要new那么多类,一层包一层,好混乱。这几天,读了java编程思想的文件IO这一章,稍微弄明白其内在逻辑,写篇博文总结总结。本文相关类依赖图都出自深入分析 Java I/O 的工作机制

基于字节流的API: InputStream 和 OutputStream

java io的API是不断演进的,最开始只有支持byte流读写的API,其基类就是InputStream和OutputStream。简单看一下各个类的关系。
InputStream
OutputStream

都是基于字节的,和字符编码没有关系:

1
2
int read(byte[] b, int off, int len)
void write(byte[] b, int off, int len

输入输出的类关系图,很相似,就以OutputStream为例说道说道,直接子类有ByteArrayOutputStream,FileOutputStream,FilterOutputStream,ObjectOutputStream,PipedOutputStream,其中FilterOutputStream类比较特殊,这是一个装饰类,其构造函数是FilterOutputStream(OutputStream out),这是个典型的装饰模式,所以我们在使用相关API的时候,需要Stream对象一层层包起来,达到一个组合的效果,例如

1
new BufferedInputStream(new FileInputStream(filename))。

下面举个文件copy的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private static void copy(String from, String to) throws IOException {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(from);
out = new FileOutputStream(to);
byte[] buf = new byte[1024];
int n = 0;
while ((n = in.read(buf)) > 0) {
out.write(buf, 0, n);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}

基于字符的API:Reader 和 Writer

可能是为了国际化,java后来推出了基于字符char的API:

1
2
int read(char[] cbuf, int off, int len)
void write(char[] cbuf, int off, int len)

Reader、Writer的子类关系图和OutputStream、InputStream很相似,都基于装饰模式。
Reader
Writer

适配器API:InputStreamReader 和 OutputStreamWriter

从基于byte的InputStream转到基于字符char的Reader,需要适配器InputStreamReader,如果字节编码格式不是系统默认的,还需要指定编码格式,例如UTF-8等,否则读入乱码,特别是中文。

1
InputStreamReader(InputStream in, String charsetName)

同样OutputStreamWriter,也充当着类似的角色。适配器模式和装饰模式类似,调用相关API,也需要一层层包起来,例如

1
new BufferedReader(new InputStreamReader(new FileInputStream(filename), "UTF-8"))

下面举个读取文件直接print的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static void display(String filename) throws IOException {
FileInputStream in = null;
BufferedReader bufReader = null;
try {
in = new FileInputStream(filename);
bufReader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String line = null;
while ((line = bufReader.readLine()) != null) {
System.out.println(line);
}
} finally {
if (in != null) {
if (bufReader != null) {
bufReader.close();
} else {
in.close();
}
}
}
}

文章目录
  1. 1. 基于字节流的API: InputStream 和 OutputStream
  2. 2. 基于字符的API:Reader 和 Writer
  3. 3. 适配器API:InputStreamReader 和 OutputStreamWriter