输入/输出流

在程序开发过程中,将输入与输出设备之间的数据传递抽象为流,例如键盘可以输入数据,显示器可以显示键盘输入的数据等。按照不同的分类方式,可以将流分为不同的类型:根据操作流的数据单元,可以将流分为字节流(操作的数据单元是一个字节)和字符流(操作的数据单元是两个字节或一个字符,因为一个字符占两个字节);根据流的流向,可以将流分为输入流和输出流。

从内存的角度出发:输入是指数据从数据源(如文件、压缩包或者视频等)流入内存中的过程,输入示意图如图15.1所示;输出是指数据从内存流出到数据源中的过程,输出示意图如图15.2所示。

image 2024 03 05 16 59 15 719
Figure 1. 图15.1 输入示意图
image 2024 03 05 16 59 41 135
Figure 2. 图15.2 输出示意图

输入流被用来读取数据,输出流被用来写入数据。

Java 语言定义了许多类专门负责各种方式的输入/输出,这些类都被放在 java.io 包中。其中,所有输入流类都是抽象类 InputStream(字节输入流)或抽象类 Reader(字符输入流)的子类,而所有输出流都是抽象类 OutputStream(字节输出流)或抽象类 Writer(字符输出流)的子类。

InputStream字节/Reader字符输入流

InputStream 类是字节输入流的抽象类,它是所有字节输入流的父类。InputStream 类的具体层次结构如图15.3所示。

image 2024 03 05 17 01 05 748
Figure 3. 图15.3 InputStream类的层次结构

该类中所有方法遇到错误时都会引发 IOException 异常。下面是对该类中的一些方法的简要说明。

  • read() 方法:从输入流中读取数据的下一个字节。返回 0~255 的 int 字节值。如果因为已经到达流末尾而没有可用的字节,则返回值为 −1。

  • read(byte[] b):从输入流中读取一定长度的字节,并以整数的形式返回字节数。

  • mark(int readlimit) 方法:在输入流的当前位置放置一个标记,readlimit 参数告知此输入流在标记位置失效之前允许读取的字节数。

  • reset() 方法:将输入指针返回当前所做的标记处。

  • skip(long n) 方法:跳过输入流上的 n 个字节并返回实际跳过的字节数。

  • markSupported() 方法:如果当前流支持 mark()/reset() 操作,就返回 true。

  • close 方法:关闭此输入流并释放与该流关联的所有系统资源。

并不是所有的 InputStream 类的子类都支持 InputStream 类中定义的所有方法,如 skip()、mark()、reset() 等方法只对某些子类有用。

Java 中的字符是 Unicode 编码的,并且是双字节的。InputStream 类是用来处理字节的,并不适合处理字符文本。Java 为字符文本的输入专门提供了一套单独的类,即 Reader 类,但 Reader 类并不是 InputStream 类的替换者,只是在处理字符串时简化了编程。Reader 类是字符输入流的抽象类,所有字符输入流的实现都是它的子类。Reader 类的具体层次结构如图15.4所示。

Reader 类中的方法与 InputStream 类中的方法类似,读者在需要时可查看 JDK 文档。

image 2024 03 05 17 05 08 589
Figure 4. 图15.4 Reader类的层次结构

OutputStream字节/Writer字符输出流

OutputStream 类是字节输出流的抽象类,此抽象类是表示输出字节流的所有类的超类。OutputStream 类的具体层次结构如图15.5所示。

OutputStream 类中的所有方法均返回 void,在遇到错误时会引发 IOException 异常。下面是对 OutputStream 类中的一些方法的简要说明。

  • write(int b) 方法:将指定的字节写入此输出流中。

  • write(byte[] b) 方法:将 b 个字节从指定的 byte 数组写入此输出流中。

  • write(byte[] b,int off,int len) 方法:将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流中。

  • flush() 方法:彻底完成输出并清空缓存区。

  • close() 方法:关闭输出流。

Writer 类是字符输出流的抽象类,所有字符输出类的实现都是它的子类。Writer 类的层次结构如图15.6所示。

image 2024 03 05 17 07 03 528
Figure 5. 图15.5 OutputStream类的层次结构
image 2024 03 05 17 07 29 175
Figure 6. 图15.6 Writer类的层次结构