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

从.dat文件加载序列化对象失败,求排查解决

问题分析与解决方案:ObjectInputStream读取对象时的重复读取问题

嘿,我看了你的代码,马上就发现了问题的根源——你的load2方法里重复调用了readObject(),这直接导致对象被跳过,Faculty根本没被处理!

核心问题拆解

你看这段判断逻辑:

if(inStream.readObject().toString().startsWith("[Student")) {
    System.out.println("FOUND A STUDENT---------");
    tempStudent = (Student) inStream.readObject();
    // ...
}
if(inStream.readObject().toString().startsWith("[Faculty")) {
    System.out.println("FOUND A FACULTY---------");
    tempFaculty = (Faculty) inStream.readObject();
    // ...
}

每次调用inStream.readObject()都会从文件流里读取下一个对象。比如:

  1. 第一次调用readObject()读取了你的Faculty对象,用来判断是不是Student——显然不是,所以跳过第一个if块
  2. 接着第二个if块又调用readObject(),这次读取的是第一个Student对象,判断是不是Faculty——也不是,跳过
  3. 循环继续,下一次第一个if调用readObject()读取第二个Student,符合条件,然后又调用一次readObject(),这时候已经到文件末尾了,直接触发EOFException

结果就是:Faculty被读取了但没处理,第一个Student被读取了但没处理,只有第二个Student被尝试加载,但也因为重复读取导致逻辑混乱,最终都没正确存入内存。

对比你的Course加载方法,它就很正确:先读取一次对象到变量,再处理,没有重复读取的问题。

修正后的load2方法

把读取对象的操作放在判断之前,先保存对象引用,再用instanceof判断类型(比依赖toString更可靠):

public void load2() {
    String fileName = "people_bag2.dat";
    FileInputStream inFile;
    ObjectInputStream inStream = null;
    Object obj; // 先统一存读取到的对象

    try {
        inFile = new FileInputStream(fileName);
        inStream = new ObjectInputStream(inFile);
        
        while (true) {
            obj = inStream.readObject(); // 只读取一次,保存引用
            if (obj instanceof Student) {
                System.out.println("FOUND A STUDENT---------");
                Student tempStudent = (Student) obj;
                // 直接使用读取到的对象,不需要重复读取
                Student person = new Student(tempStudent.getFirstName(), tempStudent.getLastName(), 
                                            tempStudent.getPhoneNumber(), tempStudent.getMajor(), 
                                            tempStudent.getCourseBag());
                add(tempStudent);
            } else if (obj instanceof Faculty) {
                System.out.println("FOUND A FACULTY---------");
                Faculty tempFaculty = (Faculty) obj;
                Faculty f = new Faculty(tempFaculty.getFirstName(), tempFaculty.getLastName(), 
                                        tempFaculty.getPhoneNumber(), tempFaculty.getTitle(), 
                                        tempFaculty.getSalary());
                add(f);
            }
        }
    } catch (EOFException e) {
        // 处理文件结束
        try {
            if(Utilities.DEBUG) {
                System.out.println("[PeopleBag]: Loaded "+fileName+" into memory successfully.");
            }
            if (inStream != null) {
                inStream.close();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    } catch (FileNotFoundException e) {
        System.out.println("File named "+ fileName +" not found.\n");
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
}

额外注意事项

  • 永远不要依赖toString()的格式来判断对象类型,instanceof是Java中判断对象类型的标准方式,更稳定可靠
  • 读取对象流时,每次readObject()都会移动流的指针,一定要确保每次只读取一次,并用变量保存引用,避免流位置混乱
  • 记得在所有异常分支里正确关闭流,或者用try-with-resources语法自动管理资源,减少资源泄漏风险

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:25:25