Java IO 按照不同类型来分,可以从以下几个方面来进行分类:
输入/输出流
字节流/字符流
-
节点流/处理流
对于前两个我们比较容易理解。那什么是节点流,什么是处理流呢。从斐青这篇文章中可以了解到:Java的IO使用装饰者模式将IO流分成了底层节点流和上层处理流。节点流直接和底层的物理存储节点关联,虽然不同的物理节点获取的节点流可能存在差异,但程序可以把不同的物理节点包装成统一的处理流,从而允许程序使用统一的IO代码来操作不同的物理节点。这就是封装的典型应用:不用考虑底层不同的节点流,只需将节点流封装成处理流来调用。
I/O流汇总
InputStream/Reader输入流
InputStream是字节输入流的抽象基类,其中有三个重要方法:
- int read()
- int read(byte[] b)
- int read(byte[] b , int off ,int len)
都是将内容以字节(byte)的形式读取到输入流中。
Read是字符输入流的抽象基类,其中有三个重要方法:
- int read()
- int read(char[] b)
- int read(char[] b , int off ,int len)
都是将内容以字符(char)的形式读取到输入流中。除此之外,两者还提供了skip()、reset()等方法。
OutputStream/Writer输入流
两个流都是从输出流写出数据到文件中,提供了如下三个方法:
- void write(byte[]/char[] b)
- void write(byte[]/char[] b, int off, int len)
- void write(int b)
因为字符流直接以字符作为操作单位, 所以Writer可以用字符串来代替字符数组(以String对象作为参数). Writer还包含如下方法:
- void write(String str)
- void write(String str, int off, int len)
- Writer append(char c)
- Writer append(CharSequence csq)
- Writer append(CharSequence csq, int start, int end)
Tips:
- 使用Java IO流执行完IO后,不能忘记关闭流,关闭流才可以保证物理资源会被回收(关闭输出流还可以保证将缓冲区中的数据flush到物理节点中,因为在执行close()方法之前,会自动执行输出流的flush()方法).
- 通常来说,字节流的功能比字符流的功能强大,因为计算机里所有的数据都是二进制的,因此字节流可以处理所有所有的二进制文件.
- 如果使用字节流来处理文本文件,则需要将这些字节转换成字符,增加了编程的复杂度.所以有一个规则:如果进行IO是文本内容,则应该考虑使用字符流;如果进行IO的是二进制内容, 则应该考虑使用字节流.
节点流/处理流
节点流的的构造参数是物理IO节点,而处理流的构造参数是已经存在的流.
常用节点流
常用处理流
在使用处理流包装了节点流之后, 关闭输入/输出流资源时, 只要关闭最上层的处理流即可.关闭最上层的处理流时, 系统会自动关闭该处理流包装的节点流.
Tips
对于缓冲流,BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter 四个缓冲流增加了缓冲功能, 可以提高IO效率, 但是需要使用flush()才可以将缓冲区的内容写入实际的物理节点。(由于它的值都保存在内存中,所以流操作完成后需要flush())。
public class BufferWriterTest {
@Test
public void testBufferedWriter() throws IOException {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("a.txt"))) {
writer.write("********");
writer.flush();
}
}
}
工具流(转换流)
- InputStreamReader将字节输入流转换成字符输入流
- OutputStreamWriter将字节输出流转换成字符输出流
参考这篇