day2
计划
- 学完IO流
笔记
1.缓冲流
字节缓冲流
- 缓冲流默认缓冲区大小为8192字节(8KB)
- 使用方式:在基本流外包装一层缓冲流
- 关闭缓冲流时,底层基本流也会自动关闭
- 性能对比
- 缓冲流逐字节读取复制:35ms(内部缓冲区已优化磁盘I/O)
- 缓冲流配合 byte[] 数组读取复制:4ms
- 缓冲流与缓冲数组同时使用是不必要的
- 缓冲流内部已有 8KB 缓冲区,逐字节读取时已通过内部缓冲区大幅减少磁盘 I/O,这是性能提升的核心
- 在缓冲流之上再使用 byte[] 数组,相当于多了一层冗余的缓冲层级,增加了内存占用和代码复杂度
- 实际开发中,单独使用缓冲流即可,或直接使用基本流配合自己的缓冲区,没必要两层都用
字符缓冲流
- BufferedReader 特有方法:
readLine(),读取一行文本,遇到文件末尾返回 null
- BufferedWriter 特有方法:
newLine(),用于多平台换行(Windows: \r\n, Linux: \n)
- 字符缓冲流也可以指定编码格式
2.转换流
- InputStreamReader:将字节输入流转换为字符输入流
- OutputStreamWriter:将字节输出流转换为字符输出流
- 可以指定编码格式,解决乱码问题
- 常与缓冲流配合使用,形成:
BufferedReader -> InputStreamReader -> FileInputStream
- Java 11+ FileReader/FileWriter 已支持指定编码,但转换流仍有用武之地
- 处理非文件来源的字节流(如网络流、内存流)
- 需要精确控制编码转换场景
3.序列化流与反序列化流
- 对象序列化:将对象写入文件,需要实现
Serializable 接口
- 对象反序列化:从文件读取对象
serialVersionUID:序列化版本号,确保反序列化时类版本一致
- 如果类结构发生变化(如新增字段),版本号不匹配会抛出
InvalidClassException
- 建议显式声明版本号,避免编译器自动生成导致的兼容性问题
transient 关键字:修饰的成员变量不参与序列化,反序列化时为默认值
- 序列化集合对象:将整个集合写入文件,便于批量操作
4.压缩流与解压缩流
ZipEntry
- 表示压缩包里的每个文件或目录
- 压缩流与解压流中有一个当前条目的概念,就是你最近获取到的或创建的ZipEntry对象
- 所以必须要及时关闭当前条目
解压缩
- 使用
ZipInputStream 读取压缩包
getNextEntry() 获取下一个 ZipEntry
- 判断是目录还是文件,分别处理
- 读取完成后调用
closeEntry() 关闭当前条目
压缩
- 使用
ZipOutputStream 写入压缩包
putNextEntry() 创建新的 ZipEntry
- 递归处理目录结构,保持原有的层级关系
- 遍历目录下所有文件和子目录
- 文件则直接写入压缩条目
- 目录则递归调用,传入更新后的路径名
- 每个文件写入完成后调用
closeEntry()
5.打印流
- PrintStream:字节打印流,
System.out 就是 PrintStream 的实例
- PrintWriter:字符打印流
- 特点
- 可以直接打印各种类型的数据(int、double、String、对象等)
- 可以设置自动刷新(autoFlush),调用
println() 时自动刷新缓冲区,换行。
6.URL网络读取
- 使用
URL 和 URLConnection 建立网络连接
- 通过
getInputStream() 获取输入流
- 使用
InputStreamReader 按字符读取网页内容
- 可以配合第三方工具包(如 Hutool)简化文件写入操作
7.工具包
- commons-io
- hutool
- 两个都是第三方工具包,提供了很多包装好的工具,导入即可直接使用。