跳至主要內容

IO

酷风大约 5 分钟

IO

  • IO 流在 Java 中分为输入流和输出流

  • InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。

  • OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。

字节流

  1. InputStream: 用于从源头(通常是文件)读取数据(字节信息)到内存中
    1. read()
      1. FileInputStream : 可直接指定文件路径
      2. BufferedInputStream: 字节缓冲输入流,new BufferedInputStream(new FileInputStream("input.txt"))
      3. DataInputStream: 读取指定类型数据,new DataInputStream(new FileInputStream("input.txt"))
      4. ObjectInputStream: 读取 Java 对象(反序列化)new ObjectInputStream(new FileInputStream("object.file"))
  2. OutputStream: 用于将数据(字节信息)写入到目的地(通常是文件)
    1. write(byte b[ ])
      1. FileOutputStream: 可直接指定文件路径
      2. BufferedOutputStream
      3. DataOutputStream:
        1. writeByte
        2. writeBoolean
      4. ObjectInputStream: 对象写入到输出流(ObjectOutputStream,序列化)

字符流

字节 vs 字符

  1. 字节流
    1. 字节(Byte)是计算机信息存储的最小单位,所以字节流可以操作所有类型的文件,每次操作1个字节;
  2. 字符流
    1. 字符流只能用操作纯文本数据,每次操作一个字符(两个字节);
    2. 字符流涉及到了缓冲区,所以在使用字符流进行写数据时,需要调用flush()或close()方法进行刷新才能将数据写入文件中。
      1. 调用flush()刷新后可以继续写数据
      2. 调用close()相当于刷新后关闭流,不能继续写数据。
    3. 字符流涉及到编码、解码工作
    4. 字符流默认采用的是 Unicode 编码,我们可以通过构造方法自定义编码。

常用字符编码

  1. utf8 :英文占 1 字节,中文占 3 字节
  2. unicode:任何字符都占 2 个字节
  3. gbk:英文占 1 字节,中文占 2 字节

字符流

  1. Reader(字符输入流)
    1. 用于从源头(通常是文件)读取数据(字符信息)到内存中
    2. java.io.Reader抽象类是所有字符输入流的父类。
    3. InputStreamReader:
      1. 字节流转换为字符流的桥梁
      2. 子类 FileReader 是基于该基础上的封装,可以直接操作字符文件。
        1. FileReader extends InputStreamReader
        2. new FileReader("input.txt");
  2. Writer(字符输出流)
    1. 用于将数据(字符信息)写入到目的地(通常是文件)
    2. java.io.Writer抽象类是所有字符输出流的父类。
    3. OutputStreamWriter:
      1. 字符流转换为字节流的桥梁
      2. 子类 FileWriter 是基于该基础上的封装,可以直接将字符写入到文件。
        1. FileWriter extends OutputStreamWriter
        2. new FileWriter("output.txt")

字节缓冲流

  • IO 操作是很消耗性能的,缓冲流将数据加载至缓冲区,一次性读取/写入多个字节,从而避免频繁的 IO 操作,提高流的传输效率。
  • 字节缓冲流这里采用了装饰器模式来增强 InputStream 和OutputStream子类对象的功能。
    • 例:可以通过 BufferedInputStream(字节缓冲输入流)来增强 FileInputStream 的功能。
    • 字节缓冲流会先将读取到的字节存放在缓存区
  • 缓冲区实际就是一个字节数组
  • 缓冲区的大小默认为 8192 字节
  1. BufferedInputStream(字节缓冲输入流)
  2. BufferedOutputStream(字节缓冲输出流)

字符缓冲流

  • BufferedReader (字符缓冲输入流)
  • BufferedWriter(字符缓冲输出流)
  • 类似于 BufferedInputStream(字节缓冲输入流)和BufferedOutputStream(字节缓冲输入流)内部都维护了一个字节数组作为缓冲区。不过,前者主要是用来操作字符信息。

打印流

  • System.out 实际是用于获取一个 PrintStream 对象
  • print方法实际调用的是 PrintStream 对象的 write 方法
  • PrintStream 是 OutputStream 的子类,PrintWriter 是 Writer 的子类。

随机访问流

  • 指的是支持随意跳转到文件的任意位置进行读写的 RandomAccessFile
  • RandomAccessFile(File file, String mode)
  • this(file, mode, false) , 默认值 openAndDelete 为 false
  • RandomAccessFile(File file, String mode, boolean openAndDelete)

IO 设计模式

装饰器模式

  • 可以在不改变原有对象的情况下拓展其功能。
  • 通过组合替代继承来扩展原始类的功能,在一些继承关系比较复杂的场景(IO 这一场景各种类的继承关系就比较复杂)更加实用。
  • 对原始类嵌套使用多个装饰器
  • 例:通过 BufferedInputStream(字节缓冲输入流)来增强 FileInputStream 的功能。
    • BufferedInputStream(InputStream in)
    • new BufferedInputStream(new FileInputStream("input.txt"))

适配器模式?

工厂模式?

IO 模型

  • IO 模型一共有 5 种:同步阻塞 I/O、同步非阻塞 I/O、I/O 多路复用、信号驱动 I/O 和异步 I/O。

Java IO 模型

  1. BIO (Blocking I/O)
    1. 同步阻塞 IO 模型
    2. 应用程序发起 read 调用后,会一直阻塞,直到内核把数据拷贝到用户空间。
  2. NIO (Non-blocking/New I/O)
    1. Java 1.4 中引入
    2. Java 中的 NIO 属于同步非阻塞 IO 模型
      1. 通过轮询操作,避免了一直阻塞。
    3. Java 中的 NIO 可以看作是 I/O 多路复用模型。
      1. 先发起 select 调用,内核数据是否准备就绪
      2. read 调用的过程(数据从内核空间 -> 用户空间)还是阻塞的。
    4. N 可以理解为 Non-blocking,不单纯是 New。它是支持面向缓冲的,基于通道的 I/O 操作方法。
    5. 高负载、高并发的(网络)应用,应使用 NIO 。可以使用少量的线程来处理多个连接。
    6. 非阻塞、面向缓冲、基于通道的 I/O
  3. AIO (Asynchronous I/O)
    1. NIO 2。Java 7 中引入了 NIO 的改进版 NIO 2,它是异步 IO 模型。
    2. 基于事件和回调机制实现
    3. 应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。

参考

上次编辑于:
贡献者: hihcoder