You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

读取文件中3个序列化对象完成后抛出java.io.EOFException问题咨询

问题根因

ObjectInputStream.readObject() 方法在读取到流末尾时不会返回null,而是直接抛出java.io.EOFException。你当前写的循环条件(o = objectInputStream.readObject()) != null永远等不到null的情况,3个对象全部读取完成后,下一次调用readObject就会触发你遇到的异常。

解决方案

以下是三种常用的修复方案,可根据业务场景选择:

方案1:捕获EOFException作为读取结束的标记

这是改动最小的方案,直接把EOFException当做读取完成的正常信号处理即可,修改后的读取代码如下:

try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file))) {
    while (true) {
        Object o = objectInputStream.readObject();
        if (o.getClass().getName().contains("Plane")) {
            Plane plane = (Plane) o;
            plane.productionYear = plane.productionYearCopy;
            plane.speed = plane.speedCopy;
            plane.engine = plane.engineCopy;
            System.out.println(plane);
        } else {
            Ship ship = (Ship) o;
            ship.productionYear = ship.productionYearCopy;
            ship.speed = ship.speedCopy;
            ship.engine = ship.engineCopy;
        }
    }
} catch (EOFException e) {
    // 属于正常读取结束,不需要打印异常
} catch (Exception e) {
    e.printStackTrace();
}

方案2:写入时先记录对象总数,读取时按数量读取

这种方式更规范,避免依赖异常做业务逻辑控制,需要同时修改写入和读取代码:

修改写入代码:

try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(file))) {
    planes.sort(Comparator.comparingInt(plane -> plane.productionYear));
    // 先写入对象总数量
    objectOutputStream.writeInt(planes.size());
    planes.forEach(plane -> {
        try {
            objectOutputStream.writeObject(plane);
        } catch (IOException e) {
            e.printStackTrace();
        }
    });
    objectOutputStream.flush();
} catch (Exception e) {
    e.printStackTrace();
}

修改读取代码:

try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file))) {
    // 先读取总数量,控制循环次数
    int count = objectInputStream.readInt();
    for (int i = 0; i < count; i++) {
        Object o = objectInputStream.readObject();
        if (o.getClass().getName().contains("Plane")) {
            Plane plane = (Plane) o;
            plane.productionYear = plane.productionYearCopy;
            plane.speed = plane.speedCopy;
            plane.engine = plane.engineCopy;
            System.out.println(plane);
        } else {
            Ship ship = (Ship) o;
            ship.productionYear = ship.productionYearCopy;
            ship.speed = ship.speedCopy;
            ship.engine = ship.engineCopy;
        }
    }
} catch (Exception e) {
    e.printStackTrace();
}

方案3:写入完成后追加一个null作为结束标记

写入所有对象后额外写一个null,读取时判断到null就结束循环,也需要同时修改读写代码:

  • 写入代码在flush()之前新增一行:objectOutputStream.writeObject(null);
  • 读取代码不需要修改,你原来的while ((o = objectInputStream.readObject()) != null )逻辑就可以正常工作

注意:如果你的业务场景中需要写入null作为有效对象,不要使用该方案

内容的提问来源于stack exchange,提问作者Vasil Petrovich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 01:24:07