IO流
一锅炖不下
  • 作用: 读写文件中的数据(读写文件, 或网络中的数据等)

  • 几个问题: 谁在读?谁在写?以什么为参照物看读写方向?程序或者内存

  • 分类

    • 按流的方向分
      • 输入流: 程序–>文件
      • 输出流: 文件–>程序
    • 按操作文件类型
      • 字节流: 所有类型文件
      • 字符流: 纯文本文件(简单理解就是用记事本打开能读懂的文件, .docx这种不算)
  • IO流体系

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    %%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': 'Microsoft YaHei'}}}%%
    graph TD
    A[IO流体系] --> B[字节流]
    A --> C[字符流]

    B --> D[字节输入流]
    B --> E[字节输出流]

    D --> F[InputStream]
    F --> F1[FileInputStream]
    F --> F2[ByteArrayInputStream]
    F --> F3[FilterInputStream]
    F3 --> F31[BufferedInputStream]
    F3 --> F32[DataInputStream]

    E --> G[OutputStream]
    G --> G1[FileOutputStream]
    G --> G2[ByteArrayOutputStream]
    G --> G3[FilterOutputStream]
    G3 --> G31[BufferedOutputStream]
    G3 --> G32[DataOutputStream]
    G3 --> G33[PrintStream]

    C --> H[字符输入流]
    C --> I[字符输出流]

    H --> J[Reader]
    J --> J1[InputStreamReader]
    J1 --> J11[FileReader]
    J --> J2[BufferedReader]
    J --> J3[StringReader]

    I --> K[Writer]
    K --> K1[OutputStreamWriter]
    K1 --> K11[FileWriter]
    K --> K2[BufferedWriter]
    K --> K3[PrintWriter]
    K --> K4[StringWriter]
    • 字节流

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      %%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': 'Microsoft YaHei'}}}%%
      graph TD
      A[字节流] --> B[字节输入流 InputStream]
      A --> C[字节输出流 OutputStream]

      B --> B1[FileInputStream]
      B --> B2[ByteArrayInputStream]
      B --> B3[FilterInputStream]
      B3 --> B31[BufferedInputStream]
      B3 --> B32[DataInputStream]
      B --> B4[ObjectInputStream]
      B --> B5[PipedInputStream]

      C --> C1[FileOutputStream]
      C --> C2[ByteArrayOutputStream]
      C --> C3[FilterOutputStream]
      C3 --> C31[BufferedOutputStream]
      C3 --> C32[DataOutputStream]
      C3 --> C33[PrintStream]
      C --> C4[ObjectOutputStream]
      C --> C5[PipedOutputStream]
    • 字符流

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      %%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': 'Microsoft YaHei'}}}%%
      graph TD
      D[字符流] --> E[字符输入流 Reader]
      D --> F[字符输出流 Writer]

      E --> E1[InputStreamReader]
      E1 --> E11[FileReader]
      E --> E2[BufferedReader]
      E --> E3[StringReader]
      E --> E4[PipedReader]

      F --> F1[OutputStreamWriter]
      F1 --> F11[FileWriter]
      F --> F2[BufferedWriter]
      F --> F3[PrintWriter]
      F --> F4[StringWriter]
      F --> F5[PipedWriter]
  • 字节流—-以FileOutputStream为例

    • 基本用法

      1. 创建流对象
      2. 读/写数据
      3. 释放资源(用try_with_resources语法可以不用手动写释放资源代码)
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      public class FOS {
      public static void main(String[] args) {
      File newFile = new File("C:\\Users\\minmin\\Desktop\\newFile.txt");
      try {
      boolean isCreated = newFile.createNewFile();
      if (isCreated) {
      // 若文件不存在, 而父级文件夹存在时, 会创建文件
      try (FileOutputStream fos = new FileOutputStream(newFile)) {
      fos.write("<UNK>".getBytes());
      }
      }
      } catch (IOException e) {
      throw new RuntimeException(e);
      }
      }
      }
    • 细节

      • 如果文件已经存在, 会清空文件重写
      • 输入整数, 会被当成ASCII码转写为字符
      • 如果不释放流资源, 文件会一直处于占用状态
      • 释放资源的语句应该写在finally块中
    • 换行和续写

      • 换行

      • 续写: 在同一个输出流中再次调用write()即可; 如果是在已有的文件内容基础上续写, 创建输出流时续写开关应为true

        1
        2
        3
        fos.write("9789newFile".getBytes());
        fos.write("\r\n".getBytes());
        fos.write("89".getBytes());
    • 循环读取

      1
      2
      3
      4
      int ch;
      while ((ch = fis.read()) != -1) {
      System.out.print((char) ch);
      }
  • 字符集

    • GBK: 两个字节存一个字符, 由于需要与ASCII兼容, 同时为了区分中英文, 中文二进制编码统一以1开头填充, ASCII字符统一以0填充高位