Java IO流:从文件操作到网络通信

Java IO 流(Input/Output Streams)是 Java 处理输入输出的核心机制,从 JDK 1.0 开始就存在,一直是文件读写、网络通信、序列化、管道等场景的基础工具。即使到了 2026 年(Java 25+ 时代),java.io 仍然是大多数日常开发中最常用、最稳定的 IO 方式,而 java.nio(NIO)和 java.nio.file(NIO.2)则在高并发、大文件、网络服务器等场景中逐渐成为主流补充。

下面从基础概念 → 分类体系 → 文件操作 → 网络通信 → 现代实践完整梳理,帮助你建立清晰的知识图谱。

1. Java IO 核心思想:一切皆流(Stream)

  • :数据像水一样从源(source)程序目的(sink) 单向流动。
  • 两种基本流:
  • 字节流(Byte Stream):处理原始二进制数据(图片、视频、exe、压缩包等),以 8 bit 为单位。
  • 字符流(Character Stream):处理文本数据(txt、json、html、源代码等),以 16 bit char 为单位,自动处理编码转换。

字节流 vs 字符流对比(2026 年最实用视角)

维度字节流 (InputStream / OutputStream)字符流 (Reader / Writer)推荐场景
数据单位byte (8 bit)char (16 bit)
编码处理不处理,需要手动自动处理(构造时指定 Charset)文本 → 字符流;二进制 → 字节流
性能稍高(无编码转换)稍低,但现代 JVM 优化差距很小
常用包装BufferedInputStream / DataOutputStreamBufferedReader / PrintWriter几乎所有场景都加 Buffered
典型子类FileInputStream, ObjectInputStreamFileReader, InputStreamReader

2. java.io 主要类层级(2026 年常用部分)

字节输入流(InputStream 家族)
InputStream(抽象)
├── FileInputStream
├── ByteArrayInputStream
├── PipedInputStream
├── FilterInputStream(装饰器基类)
│ ├── BufferedInputStream(最常用缓冲)
│ ├── DataInputStream(读基本类型)
│ ├── PushbackInputStream
│ └── ObjectInputStream(反序列化)

字节输出流(OutputStream 家族)
OutputStream(抽象)
├── FileOutputStream
├── ByteArrayOutputStream
├── PipedOutputStream
├── FilterOutputStream
│ ├── BufferedOutputStream
│ ├── DataOutputStream
│ └── ObjectOutputStream(序列化)

字符输入流(Reader 家族)
Reader(抽象)
├── FileReader(= InputStreamReader + FileInputStream + 默认编码)
├── InputStreamReader(字节 → 字符桥梁)
├── BufferedReader(最常用,按行读)
├── CharArrayReader
└── StringReader

字符输出流(Writer 家族)
Writer(抽象)
├── FileWriter
├── OutputStreamWriter(字符 → 字节桥梁)
├── BufferedWriter
├── PrintWriter(最常用,println / printf)
├── CharArrayWriter
└── StringWriter

装饰器模式是 java.io 的灵魂:基流 + 各种 Filter 层层包装,实现缓冲、数据类型转换、对象序列化等功能。

3. 文件操作经典写法(2026 年推荐模板)

3.1 字节方式复制文件(通用、高性能)

public static void copyFile(String src, String dest) throws IOException {
    try (InputStream  in  = new BufferedInputStream(new FileInputStream(src));
         OutputStream out = new BufferedOutputStream(new FileOutputStream(dest))) {

        byte[] buf = new byte[8192];   // 8KB 缓冲(经验值)
        int len;
        while ((len = in.read(buf)) != -1) {
            out.write(buf, 0, len);
        }
    }
}

3.2 文本方式按行读取(最常用)

public static List<String> readLines(String path) throws IOException {
    List<String> lines = new ArrayList<>();
    try (BufferedReader reader = Files.newBufferedReader(Paths.get(path), StandardCharsets.UTF_8)) {
        String line;
        while ((line = reader.readLine()) != null) {
            lines.add(line);
        }
    }
    return lines;
}

3.3 现代推荐:java.nio.file.Files(Java 7+,极大简化)

// 读全部文本(小文件)
String content = Files.readString(Path.of("config.json"), StandardCharsets.UTF_8);

// 写全部文本
Files.writeString(Path.of("log.txt"), "hello\nworld", StandardCharsets.UTF_8, StandardOpenOption.APPEND);

// 复制文件
Files.copy(Path.of("src.jpg"), Path.of("backup.jpg"), StandardCopyOption.REPLACE_EXISTING);

// 遍历目录(深度优先)
try (Stream<Path> stream = Files.walk(Paths.get("project"))) {
    stream.filter(Files::isRegularFile)
          .forEach(System.out::println);
}

4. 网络通信中的 IO 流(Socket 经典用法)

4.1 同步阻塞式(BIO) – 最简单、最常用入门

// 服务端
try (ServerSocket server = new ServerSocket(8080)) {
    while (true) {
        Socket socket = server.accept();           // 阻塞等待客户端
        try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {

            String line;
            while ((line = in.readLine()) != null) {
                System.out.println("收到: " + line);
                out.println("Echo: " + line.toUpperCase());
            }
        }
    }
}

问题:每个连接占用一个线程 → 高并发下线程爆炸(C10K 问题)。

4.2 现代高并发方向(2026 年主流)

  • NIO(Selector + Channel + Buffer):单线程处理多连接(Netty 底层就是 NIO 封装)
  • AIO(AsynchronousSocketChannel):回调/CompletableFuture 风格
  • 虚拟线程(Java 21+ Loom 项目):用同步代码 + 百万虚拟线程,极大简化高并发网络 IO

示例(虚拟线程 + 同步风格,效果媲美异步):

// Java 21+ 推荐方式
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    ServerSocket server = new ServerSocket(8080);
    while (true) {
        Socket socket = server.accept();
        executor.submit(() -> handleClient(socket));  // 每个连接一个虚拟线程
    }
}

5. 快速决策表(2026 年选型指南)

场景推荐方式为什么
小文件 / 简单脚本Files.readString / writeString最简洁、无需 try-with-resources 手动关闭
大文件复制 / 二进制处理Buffered + byte[8192] 循环性能好、内存可控
文本逐行处理(日志、配置)BufferedReader + Files.newBufferedReader内存友好、支持大文件
对象序列化ObjectInput/OutputStream简单,但不推荐新项目(用 JSON/Protobuf)
高并发网络服务器Netty(基于 NIO) 或 虚拟线程 + BIO兼顾开发效率与性能
超大文件(GB+)java.nio.channels.FileChannel支持内存映射、零拷贝

掌握了以上内容,你已经能应对 90% 的 IO 场景。

如果你当前最常碰到的痛点是:

  • 文件乱码?
  • 大文件 OOM?
  • Socket 高并发卡死?
  • 想迁移到 NIO / Netty?
  • 虚拟线程在 IO 中的最佳实践?

告诉我具体场景,我可以给你更针对性的代码模板或优化方案。

文章已创建 4237

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部