day2 IO流

day2

计划

  1. 学完IO流

笔记

1.缓冲流

字节缓冲流
  1. 缓冲流默认缓冲区大小为8192字节(8KB)
  2. 使用方式:在基本流外包装一层缓冲流
  3. 关闭缓冲流时,底层基本流也会自动关闭
  4. 性能对比
    1. 缓冲流逐字节读取复制:35ms(内部缓冲区已优化磁盘I/O)
    2. 缓冲流配合 byte[] 数组读取复制:4ms
  5. 缓冲流与缓冲数组同时使用是不必要的
    1. 缓冲流内部已有 8KB 缓冲区,逐字节读取时已通过内部缓冲区大幅减少磁盘 I/O,这是性能提升的核心
    2. 在缓冲流之上再使用 byte[] 数组,相当于多了一层冗余的缓冲层级,增加了内存占用和代码复杂度
    3. 实际开发中,单独使用缓冲流即可,或直接使用基本流配合自己的缓冲区,没必要两层都用
字符缓冲流
  1. BufferedReader 特有方法:readLine(),读取一行文本,遇到文件末尾返回 null
  2. BufferedWriter 特有方法:newLine(),用于多平台换行(Windows: \r\n, Linux: \n)
  3. 字符缓冲流也可以指定编码格式

2.转换流

  1. InputStreamReader:将字节输入流转换为字符输入流
  2. OutputStreamWriter:将字节输出流转换为字符输出流
  3. 可以指定编码格式,解决乱码问题
  4. 常与缓冲流配合使用,形成:BufferedReader -> InputStreamReader -> FileInputStream
  5. Java 11+ FileReader/FileWriter 已支持指定编码,但转换流仍有用武之地
    1. 处理非文件来源的字节流(如网络流、内存流)
    2. 需要精确控制编码转换场景

3.序列化流与反序列化流

  1. 对象序列化:将对象写入文件,需要实现 Serializable 接口
  2. 对象反序列化:从文件读取对象
  3. serialVersionUID:序列化版本号,确保反序列化时类版本一致
    1. 如果类结构发生变化(如新增字段),版本号不匹配会抛出 InvalidClassException
    2. 建议显式声明版本号,避免编译器自动生成导致的兼容性问题
  4. transient 关键字:修饰的成员变量不参与序列化,反序列化时为默认值
  5. 序列化集合对象:将整个集合写入文件,便于批量操作

4.压缩流与解压缩流

ZipEntry
  1. 表示压缩包里的每个文件或目录
  2. 压缩流与解压流中有一个当前条目的概念,就是你最近获取到的或创建的ZipEntry对象
  3. 所以必须要及时关闭当前条目
解压缩
  1. 使用 ZipInputStream 读取压缩包
  2. getNextEntry() 获取下一个 ZipEntry
  3. 判断是目录还是文件,分别处理
  4. 读取完成后调用 closeEntry() 关闭当前条目
压缩
  1. 使用 ZipOutputStream 写入压缩包
  2. putNextEntry() 创建新的 ZipEntry
  3. 递归处理目录结构,保持原有的层级关系
    1. 遍历目录下所有文件和子目录
    2. 文件则直接写入压缩条目
    3. 目录则递归调用,传入更新后的路径名
  4. 每个文件写入完成后调用 closeEntry()

5.打印流

  1. PrintStream:字节打印流,System.out 就是 PrintStream 的实例
  2. PrintWriter:字符打印流
  3. 特点
    1. 可以直接打印各种类型的数据(int、double、String、对象等)
    2. 可以设置自动刷新(autoFlush),调用 println() 时自动刷新缓冲区,换行。

6.URL网络读取

  1. 使用 URLURLConnection 建立网络连接
  2. 通过 getInputStream() 获取输入流
  3. 使用 InputStreamReader 按字符读取网页内容
  4. 可以配合第三方工具包(如 Hutool)简化文件写入操作

7.工具包

  1. commons-io
  2. hutool
  3. 两个都是第三方工具包,提供了很多包装好的工具,导入即可直接使用。