Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

  • Java并发

  • Java IO

    • Java IO概述
    • IO基础

      • IO流体系
        • 1. 什么是流
        • 2. 四大基础抽象
        • 3. 字节流体系
        • 4. 字符流体系
        • 5. 节点流和处理流
          • 5.1 节点流
          • 5.2 处理流
        • 6. 选择流的基本原则
        • 7. 常见误区
        • 专家实践清单
        • Tips 快问快答
        • 8. 总结
      • 字节流
      • 字符流
      • 字节流与字符流的转换
      • 装饰器模式与IO设计
    • 常用IO流

    • 文件与目录操作

    • Java NIO

    • 高级主题

    • 实践与性能优化

    • 面试与设计题

    • IO实践速查

  • JVM

目录

IO流体系

理解 Java IO,第一步不是记住所有类名,而是建立“流体系”的地图。Java IO 的类非常多,但大部分都围绕四个基础抽象展开:InputStream、OutputStream、Reader、Writer。

# 1. 什么是流

流可以理解为数据传输的管道。数据从一端流向另一端,程序只需要按照顺序读取或写入。

读取文件:文件 -> 输入流 -> Java 程序
写入文件:Java 程序 -> 输出流 -> 文件

流的好处是屏蔽底层数据源差异。无论数据来自文件、内存、网络还是压缩包,只要抽象成流,程序就可以用相似的方式处理。

# 2. 四大基础抽象

Java IO 的四个基础抽象类如下:

类 数据方向 数据单位 说明
InputStream 输入 字节 所有字节输入流的父类
OutputStream 输出 字节 所有字节输出流的父类
Reader 输入 字符 所有字符输入流的父类
Writer 输出 字符 所有字符输出流的父类

这四个类共同回答两个问题:

  • 数据是读进来还是写出去?
  • 数据按字节处理还是按字符处理?

# 3. 字节流体系

字节流以 byte 为最小处理单位,适合所有二进制数据。

常见字节输入流:

  • FileInputStream:从文件读取字节。
  • BufferedInputStream:为字节输入增加缓冲。
  • ByteArrayInputStream:从内存字节数组读取。
  • DataInputStream:读取 Java 基本数据类型。
  • ObjectInputStream:读取序列化对象。

常见字节输出流:

  • FileOutputStream:向文件写入字节。
  • BufferedOutputStream:为字节输出增加缓冲。
  • ByteArrayOutputStream:向内存字节数组写入。
  • DataOutputStream:写入 Java 基本数据类型。
  • ObjectOutputStream:写入序列化对象。

# 4. 字符流体系

字符流以 char 或字符数据为处理单位,适合文本内容。

常见字符输入流:

  • FileReader:从文件读取字符。
  • BufferedReader:增加缓冲,支持按行读取。
  • InputStreamReader:把字节输入流转换为字符输入流。
  • StringReader:从字符串读取字符。

常见字符输出流:

  • FileWriter:向文件写入字符。
  • BufferedWriter:增加缓冲,支持写入换行。
  • OutputStreamWriter:把字节输出流转换为字符输出流。
  • StringWriter:向字符串缓冲区写入字符。

# 5. 节点流和处理流

从设计上看,IO 流还可以分为节点流和处理流。

# 5.1 节点流

节点流直接连接数据源或数据目标。

例如:

  • FileInputStream 直接读取文件。
  • FileOutputStream 直接写文件。
  • ByteArrayInputStream 直接读取内存数组。
  • SocketInputStream 直接读取网络连接。

节点流负责“接触真实资源”。

# 5.2 处理流

处理流包装在其他流外层,对原始能力进行增强。

例如:

  • BufferedInputStream 提供缓冲能力。
  • DataInputStream 提供基本类型读写能力。
  • ObjectInputStream 提供对象反序列化能力。
  • InputStreamReader 提供字节到字符的转换能力。

处理流负责“增强已有流”。

try (InputStream input = new BufferedInputStream(new FileInputStream("data.bin"))) {
    byte[] buffer = new byte[1024];
    int len = input.read(buffer);
}

这里 FileInputStream 是节点流,BufferedInputStream 是处理流。

# 6. 选择流的基本原则

实际开发中可以按照下面的问题选择:

  1. 处理的是文本还是二进制?

    • 文本:优先使用字符流。
    • 二进制:必须使用字节流。
  2. 是否需要指定字符集?

    • 需要:使用 InputStreamReader、OutputStreamWriter 或 Files.newBufferedReader。
    • 不需要但希望代码明确:也建议显式指定 StandardCharsets.UTF_8。
  3. 文件是否较大?

    • 较大:使用缓冲流或 NIO。
    • 很大:避免一次性读入内存。
  4. 是否需要随机读写?

    • 需要:考虑 RandomAccessFile 或 FileChannel。
  5. 是否是高并发网络场景?

    • 是:考虑 NIO、Netty 等基于多路复用的方案。

# 7. 常见误区

  • 不要用字符流处理图片、视频、压缩包等二进制文件。
  • 不要在循环中频繁单字节读取大文件,应该使用缓冲区。
  • 不要依赖平台默认字符集,跨环境部署时容易乱码。
  • 不要忘记关闭流,文件描述符泄漏会导致线上故障。
  • 不要把大文件一次性读入 byte[] 或 String。

# 专家实践清单

检查项 判断标准 风险信号
数据单位 文本用字符流,二进制用字节流 用 Reader 处理图片、压缩包
资源所有权 谁创建谁关闭,外部传入要写清契约 工具方法关闭调用方传入的流
缓冲策略 高频小 IO 使用缓冲 循环单字节读写
字符集 文本读写显式指定编码 使用平台默认编码
大文件 分块或流式处理 readAllBytes 读取超大文件

问题定位时可以按下面的链路倒推:

数据源
  │ 字节/字符
  ▼
节点流
  │ 文件、网络、内存
  ▼
处理流
  │ 缓冲、转换、对象、数据
  ▼
业务代码
  │ 解析、校验、持久化
  ▼
资源关闭与异常处理

# Tips 快问快答

Q:Java IO 流体系最核心的四个抽象是什么? A:InputStream、OutputStream、Reader、Writer,分别描述方向和数据单位。

Q:节点流和处理流有什么区别? A:节点流直接连接数据源,处理流包装其他流并增强能力。

Q:为什么 IO 类这么多? A:Java IO 通过装饰器模式拆分能力,不同类负责不同维度的增强。

Q:什么时候用字节流? A:处理二进制、网络协议、压缩包、图片、视频等原始字节数据。

Q:什么时候用字符流? A:处理文本,并且需要按字符集编码或解码时。

Q:为什么要用缓冲流? A:减少底层系统调用次数,提高频繁小块读写的效率。

Q:流关闭为什么重要? A:流背后可能占用文件描述符、Socket、堆外内存等外部资源。

Q:IO 选型第一步是什么? A:先判断数据是文本还是二进制,再判断来源、大小、访问方式和可靠性要求。

# 8. 总结

Java IO 流体系看起来庞大,但主干非常清晰:四个基础抽象负责方向和数据单位,节点流负责连接真实资源,处理流负责增强能力。掌握这条主线后,再学习具体类就会容易很多。

上次更新: 2026/06/25, 14:19:18
Java IO概述
字节流

← Java IO概述 字节流→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式