源本科技 | 码上会

Java I/O

2026/01/30
51
0

学习目标

  • 理解 Java I/O 的基本概念与核心组件

  • 掌握标准输入输出流 System.inSystem.outSystem.err 的使用方式

  • 区分字节流(Byte Stream)与字符流(Character Stream)的适用场景

  • 能够使用常见 I/O 类完成文件读写操作

  • 了解格式化输出(printf)的用法


什么是 Java I/O

Java I/O(Input/Output)是 java.io 包中提供的一套用于处理数据输入与输出的类和流。它支持从多种(如文件、键盘、网络)读取数据,并将数据写入到目标(如文件、控制台、Socket)。

Java I/O 提供两类流:

  • 字节流(Byte Streams):处理原始 8 位字节数据,适用于二进制文件(如图片、音频)

  • 字符流(Character Streams):处理 16 位 Unicode 字符,适用于文本文件,自动处理编码转换


标准 I/O 流

Java 预定义了三个最常用的标准流,无需显式创建即可直接使用:

类型

作用

System.in

InputStream

标准输入(通常来自键盘)

System.out

PrintStream

标准输出(通常显示在控制台)

System.err

PrintStream

标准错误输出(独立于正常输出,便于调试)


1. System.in

标准输入

System.in 是一个 InputStream,但直接使用较繁琐,通常配合 ScannerBufferedReader 使用。

基础用法示例(直接读取字节):

import java.io.IOException;

public class InputExample {
    public static void main(String[] args) throws IOException {
        System.out.println("请输入一个字符:");

        int data = System.in.read();  // 读取一个字节
        System.out.println("你输入的是:" + (char) data);
        System.out.println("对应的 ASCII 值:" + data);
    }
}

实际开发中更推荐使用 Scanner

Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();

2. System.out

准输出

提供三种常用输出方法:

print()

不换行输出

System.out.print("你好 ");
System.out.print("世界!");
// 输出:你好 世界!

println()

换行输出

System.out.println("第一行");
System.out.println("第二行");
// 输出:
// 第一行
// 第二行

printf()

格式化输出

支持类似 C 语言的格式化语法,功能强大:

public class FormatOutput {
    public static void main(String[] args) {
        int count = 42;
        double pi = Math.PI;

        System.out.printf("数量:%d%n", count);                // %d 整数
        System.out.printf("圆周率:%.2f%n", pi);              // %.2f 保留两位小数
        System.out.printf("右对齐:%10.2f%n", pi);            // 总宽度 10,右对齐
        System.out.printf("姓名:%s,年龄:%d%n", "张三", 25);   // 多参数格式化
    }
}

输出:

数量:42
圆周率:3.14
右对齐:      3.14
姓名:张三,年龄:25

%n 是 Java 推荐的跨平台换行符(等价于 \n 在 Linux/macOS,\r\n 在 Windows)


3. System.err

标准错误输出

用法与 System.out 完全一致,但用于输出错误信息,便于日志分离或重定向。

public class ErrorOutput {
    public static void main(String[] args) {
        System.err.println("发生了一个严重错误!");
        System.err.printf("错误代码:%d - %s%n", 500, "服务器内部错误");
    }
}

在命令行中,可通过 2> 将错误流重定向到文件:

java ErrorOutput 2> error.log

流的分类

按方向分类

类型

说明

常见类

输入流

从源读取数据

FileInputStream, BufferedInputStream

输出流

向目标写入数据

FileOutputStream, BufferedOutputStream

按数据类型分类

字节流

  • 处理 8 位字节byte

  • 适用于二进制数据(图片、视频、压缩包等)

  • 核心抽象类:InputStream / OutputStream

常用字节流类:

用途

FileInputStream / FileOutputStream

读写文件

BufferedInputStream / BufferedOutputStream

带缓冲,提升性能

DataInputStream / DataOutputStream

读写基本数据类型(int, double 等)

PrintStream

支持 print() / println()

示例:使用字节流复制文件

import java.io.*;

public class FileCopyByte {
    public static void main(String[] args) throws IOException {
        try (FileInputStream in = new FileInputStream("source.txt");
             FileOutputStream out = new FileOutputStream("copy.txt")) {

            int byteRead;
            while ((byteRead = in.read()) != -1) {
                out.write(byteRead);
            }
        } // 自动关闭资源(try-with-resources)
    }
}

推荐使用 try-with-resources 语法自动关闭流,避免资源泄漏


字符流

  • 处理 16 位 Unicode 字符

  • 适用于文本数据,自动处理字符编码(如 UTF-8)

  • 核心抽象类:Reader / Writer

常用字符流类:

用途

FileReader / FileWriter

读写文本文件

BufferedReader / BufferedWriter

带缓冲的字符流

InputStreamReader / OutputStreamWriter

在字节流与字符流之间转换

PrintWriter

支持格式化文本输出

示例:逐字符读取文本文件

import java.io.*;

public class ReadTextFile {
    public static void main(String[] args) throws IOException {
        try (FileReader reader = new FileReader("test.txt")) {
            int ch;
            while ((ch = reader.read()) != -1) {
                System.out.print((char) ch);
            }
        }
    }
}

更高效的方式是使用 BufferedReader 按行读取:

BufferedReader br = new BufferedReader(new FileReader("test.txt"));
String line;
while ((line = br.readLine()) != null) {
    System.out.println(line);
}

字节流 vs 字符流

场景

推荐流类型

读写图片、音频、视频、ZIP 文件等

字节流

读写 .txt.csv.log 等文本文件

字符流

需要处理中文或其他非 ASCII 文本

字符流(避免乱码)

网络传输原始数据

字节流


重点总结

  • Java I/O 分为字节流字符流,分别用于二进制和文本数据

  • System.in/out/err 是三大标准流,日常调试和交互必备

  • printf() 提供强大的格式化输出能力

  • 文件操作应优先使用 try-with-resources 确保资源释放

  • 文本处理优先选择字符流(如 FileReader + BufferedReader),避免编码问题


思考题

  1. 为什么读取包含中文的文本文件时,使用 FileInputStream 可能出现乱码?而 FileReader 不会?

  2. BufferedInputStreamBufferedReader 的“缓冲”机制是如何提升 I/O 性能的?

  3. 如果需要将一个大文件(如 1GB 视频)从磁盘复制到另一个位置,使用单字节读写(read()/write())效率很低,应如何优化?