时间飞逝,转眼就是2016,由于2015下半年事情太多,就把读书这事给松懈了,现在捡起来继续。
平时用java io主要是读写文件,网络传输方面基本不涉及。用java io API给我的最大感受就是读写一下文件,为啥要new那么多类,一层包一层,好混乱。这几天,读了java编程思想的文件IO这一章,稍微弄明白其内在逻辑,写篇博文总结总结。本文相关类依赖图都出自深入分析 Java I/O 的工作机制
java io的API是不断演进的,最开始只有支持byte流读写的API,其基类就是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很相似,都基于装饰模式。
从基于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(); } } } }
|