1. I/O 流分类

  • 按照数据流的方向

    • 输入流:文件 \to 程序

    • 输出流:程序 \to 文件

输入流和输出流都是站在程序的角度上来说的

  • 按照处理数据单位

    • 字节流

      最原始的一个流,读出来的数据就是类似 01010101 这种最底层的数据表示形式;

      按照一个字节一个字节来读

    • 字符流

      按照一个字符一个字符地往外读取数据(一个字符是 2 个字节)

  • 按照功能

    • 节点流

      节点流可以从或向一个特定的地方(节点)读写数据,直接跟数据源相接

    • 处理流

      处理流用来包装节点流,是对一个已存在的流(节点流或处理流)的连接和封装,通过所封装的流的功能调用实现数据读写,不会直接与数据源相连

JDK 所提供的所有流类型位于包 java.io 内,都分别继承自以下四种抽象流类型:

  • 输入流:

    • InputStream(字节流)
    • Reader(字符流)
  • 输出流:

    • OutputStream(字节流)
    • Writer(字符流)

2. InputStream

  • 凡是以 InputStream 结尾的流类型,都是以字节的形式向程序输入数据

  • 继承自 InputStream 的流都是用于向程序中输入数据,且数据的单位为字节(8 bit)

InputStream 的基本方法:

  • int read() throws IOException - 从输入流中读取一个字节的数据,每读取一个字节,就处理一个字节==(如果读取结束,返回的是 -1)==

  • int read(byte b[]) throws IOException - 从流中读取字节并存储在指定的数组中,然后再处理数组里面的数据==(如果读取结束返回 -1)==

  • int read(byte b[], int off, int len) throws IOException - 从输入流中读取最多 len 个字节,并将其存储在缓冲区数组 b 中,从偏移量 off 开始存储==(如果遇到流尾部,返回 -1)==

  • long skip(long n) throws IOException - 从输入流中跳过并丢弃 n 个字节的数据

  • int available() throws IOException - 返回输入流中可用的字节数

  • void close() throws IOException - 关闭输入流

3. OutputStream

  • 继承自 OutputStream 的流是用于程序中输出数据,且数据的单位为字节(8 bit)

OutputStream 的方法:

  1. void write(int b) throws IOException - 将指定的字节写入输出流(写入低8位,忽略高24位)
  2. write(byte b[]) throws IOException - 把字节数组中所有数据写入到输出流中
  3. void write(byte b[], int off, int len) throws IOException - 将指定字节数组的一部分写入输出流,从偏移量 off 开始,写入长度为 len 的字节
  4. void flush() throws IOException - 强制将输出流中存在的所有数据写入目标
  5. void close() throws IOException - 关闭输出流

4. Reader

和 InputStream 一模一样,唯一的区别就在于读的数据单位不同

继承自 Reader 的流都是用于向程序中输入数据,且数据的单位为字符(16 bit)

Reader 的基本方法:

  • boolean ready() throws IOException - 检查 Reader 流是否准备好读取
  • int read() throws IOException - 从输入流中读取单个字符
  • int read(char cbuf[]) throws IOException - 从流中读取字符并存储在指定的数组中
  • int read(char cbuf[], int off, int len) throws IOException - 从流中读取 len 长度的字符数,并从 off 开始存储在指定的数组中
  • long skip(long n) throws IOException - 从流中丢弃指定数量的字符
  • void close() throws IOException - 关闭输入流

5. Writer

继承自Writer的流都是用于程序中输出数据,且数据的单位为字符(16 bit)

Writer 的基本方法:

  • void write(int c) throws IOException - 写一个字符
  • void write(char cbuf[]) throws IOException - 写一个字符数组
  • void write(char cbuf[], int off, int len) throws IOException - 写一个字符数组的一部分,off 为开始索引,len 为字符个数
  • void write(String str) throws IOException - 写一个字符串
  • void write(String str, int off, int len) throws IOException - 写一个字符串的一部分,off 指定要写入的子串在 str 中的起始位置,len 指定要写入的子串的长度
  • void flush() throws IOException - 强制将输出流中存在的所有数据写入目标
  • void close() throws IOException - 关闭输出流

一定要及时关闭流,否则可能造成无法读写数据。

6. 处理流

6.1 缓冲流

缓冲流可分为以下 4 类:

  1. BufferedReader

    BufferedReader 提供了 readLine() 方法用于读取一行字符串

  2. BufferedWriter

    BufferedWriter 提供了 newLine() 用于写入一个行分隔符

  3. BufferedInputStream

  4. BufferedOutputStream

BufferedReader 类为例,其构造函数有:

  1. BufferedReader(Reader in)
  2. BufferedReader(Reader in, int sz) - 其中参数 sz 表示缓冲区大小

对于输出的缓冲流,写出的数据会现在内存中缓存,使用 flush() 方法将会使内存中的数据立刻写出

6.2 转换流

转换流非常的有用,它可以把一个字节流转换成一个**字符流**。

转换流分为两种:

  1. InputStreamReader

    • InputStream 流转换成 Reader 流;
    • 需要和 InputStream “套接”
  2. OutputStreamWriter

    • OutputStream 流转换成 Writer 流;

    • 需要和 OutputStream “套接”

6.3 数据流
  • DataInputStream

    继承自 InputStream

    需要”套接“在 InputStream 类型的节点流上

    构造函数:DataInputStream(InputStream in)

  • DataOutputStream

    继承自 OutputStream

    需要“套接”在 OutputStream 类型的节点流上

    构造函数:DataOutputStream(OutputStream out)

6.4 打印流
  • PrintWriterPrintStream 都属于输出流,分别针对与字符和字节
  • PrintWriterPrintStream 提供了重载的 print() 方法和println() 方法,用于多种数据类型的输出
  • PrintWriterPrintStream 的输出操作不会抛出异常,用户通过检测错误状态获取错误信息
  • PrintWriterPrintStream 有自动 flush 功能
6.5 对象流

直接将 Object 写入或读出

  • transient 关键字:用它来修饰的成员变量在序列化的时候不予考虑,也就是当成不存在

  • Serializable 接口:一个对象序列化的标记性接口,一个类只有实现了 Serializable 接口,它的对象才能被序列化

  • Externalizable 接口:自定义序列化和反序列化,需要实现 writeExternal()readExternal() 方法