跳到内容

元数据卡

  • 前置知识:异常处理(第11章)
  • 预计时间:15 分钟
  • 完成标志:能用字节流和字符流读写文件

你的程序不能永远活在内存里。你可以创建一把宝剑对象——但程序一关,全没了。怎么保存冒险成果?怎么读取远方的战报?

这就是 I/O——Input/Output,程序跟外部世界对话的桥梁。

字节流:InputStream 与 OutputStream

老陈师傅递给你一张羊皮卷轴:"把这张地图抄到另一张纸上。"地图不是文字——是一个字节一个字节的二进制数据。Java 最基础的 I/O 抽象就是字节流。

java
// FileInputStream / FileOutputStream 把图片复制一份
import java.io.*;
public class CopyBytes {
    public static void main(String[] args) throws IOException {
        try (InputStream in = new FileInputStream("map.jpg");
             OutputStream out = new FileOutputStream("map_copy.jpg")) {
            byte[] buf = new byte[4096];
            int n;
            while ((n = in.read(buf)) != -1) out.write(buf, 0, n);
        }
        System.out.println("复制完成");
    }
}

运行: 放一张 map.jpgjava CopyBytes.java(Java 11+)。 输出: "复制完成",出现 map_copy.jpg

read() 返回实际读到的字节数,-1 表示读完了。

字符流:Reader 与 Writer

"如果我读的是战报信呢?"字节流只认识 byte,但文本需要编码——"敌"字在 UTF-8 里占 3 个字节。按字节读你看到的是碎片数字。

ReaderWriter 自动处理编码转换。

java
import java.io.*;
import java.nio.charset.StandardCharsets;
public class ReadDispatch {
    public static void main(String[] args) throws IOException {
        try (BufferedReader r = new BufferedReader(
                new FileReader("dispatch.txt", StandardCharsets.UTF_8))) {
            String line;
            while ((line = r.readLine()) != null) System.out.println(line);
        }
    }
}

运行: 写一个含中文的 dispatch.txtjava ReadDispatch.java输出: 逐行打印,中文正常。

字节 vs 字符

场景理由
图片/音频/视频InputStream / OutputStream二进制,不需要编码
文本文件 (.txt/.csv/.json)Reader / Writer自动处理编码
不确定类型InputStream不会损坏数据

缓冲流:BufferedXxx

每次 read() 都找硬盘——一次几毫秒,大文件上万次就拖垮你。缓冲流加了 8KB 内部缓冲区。

java
import java.io.*;
public class BufferCompare {
    public static void main(String[] args) throws IOException {
        long start = System.currentTimeMillis();
        try (InputStream in = new FileInputStream("big.dat")) {
            while (in.read() != -1) { /* 空读 */ }
        }
        System.out.println("无缓冲: " + (System.currentTimeMillis() - start) + "ms");

        start = System.currentTimeMillis();
        try (BufferedInputStream in = new BufferedInputStream(
                new FileInputStream("big.dat"))) {
            while (in.read() != -1) { /* 空读 */ }
        }
        System.out.println("有缓冲: " + (System.currentTimeMillis() - start) + "ms");
    }
}

运行: 生成 10MB 文件 dd if=/dev/urandom of=big.dat bs=1M count=10输出: 有缓冲比无缓冲快几十倍。

对象序列化:ObjectXxx

你的盔甲对象——有名字、防御值、耐久度——想完整存到文件,下次还能恢复。

java
import java.io.*;
class Armor implements Serializable {
    String name; int def, dur;
    Armor(String n, int d, int dr) { name = n; def = d; dur = dr; }
    public String toString() { return name + " (防" + def + " 耐" + dur + ")"; }
}
public class SerializeDemo {
    public static void main(String[] args) throws Exception {
        try (ObjectOutputStream o = new ObjectOutputStream(
                new FileOutputStream("armor.dat"))) {
            o.writeObject(new Armor("铁甲", 50, 100));
        }
        try (ObjectInputStream i = new ObjectInputStream(
                new FileInputStream("armor.dat"))) {
            System.out.println("恢复: " + i.readObject());
        }
    }
}

运行: java SerializeDemo.java输出: 恢复: 铁甲 (防50 耐100)

三个关键点:实现 Serializable(标记接口,无方法);serialVersionUID 是版本号;transient 字段不序列化。

try-with-resources:永远别忘关流

每个流占用系统资源——文件句柄不关,跑久了会 Too many open files

java
// 老写法:finally 里手动关,又臭又长
InputStream in = null;
try { in = new FileInputStream("data.txt"); } finally {
    if (in != null) try { in.close(); } catch (IOException e) { }
}

// 现代写法(Java 7+)
try (InputStream in = new FileInputStream("data.txt")) { /* 自动关 */ }

// 多个资源
try (InputStream in = new FileInputStream("a.txt");
     OutputStream out = new FileOutputStream("b.txt")) { /* 都自动关 */ }

// Java 9+:外部声明
InputStream in = new FileInputStream("a.txt");
try (in) { /* 一样 */ }

实现了 AutoCloseable 的类就能放进 try (...) 里——InputStream、OutputStream、Reader、Writer 都已支持。


旅人笔记

字节流(InputStream/OutputStream)管二进制,字符流(Reader/Writer)管文本。缓冲流加速 I/O。序列化让对象走出程序。永远用 try-with-resources。

下一站:文件与目录操作

学会了读写流,下一步操作文件本身——遍历目录、过滤文件名、递归查找。

进入文件与目录操作 →

Built with VitePress | Software Systems Atlas