序列化过程不断地覆盖自己?

Serialization process constantly overwrites itself?

我是 java 的新手,正在尝试在我的项目中进行一些序列化。我有一堆名为 Student 的对象,我想将它们序列化。我为此使用的代码如下:

  try{
                    for(Student s: students){ 
                    FileOutputStream fileOut = new FileOutputStream("C:/Users/Jaimee-Lee/Desktop/Advanced programming work/MilestoneOne/student.ser");
                    ObjectOutputStream out = new ObjectOutputStream(fileOut);
                    out.writeObject(s);
                    out.close();
                    fileOut.close();
                    }
                    System.out.printf("Serialized data is saved in /MilestoneOne/student.ser \n");
                    

                }catch(IOException i){
                    i.printStackTrace();
                }

我发现的问题是我使用的学生数组有 20 个学生 (S1 - S20)。当我尝试反序列化对象时,它只给我包含最后一个被序列化的学生的对象 (S20)

这是我的反序列化代码:

for(Student student : students){
                System.out.println(student.getStudentID());
            }

            try(FileInputStream fis = new FileInputStream("student.ser");
                    ObjectInputStream ois = new ObjectInputStream(fis)){
                        while(fis.available() > 0 ){
                            deserializedStudents.add((Student) ois.readObject());
                            System.out.println("Added");
                        }

                        System.out.println(Arrays.toString(deserializedStudents.toArray()));
                        deserializedStudents.forEach(student -> System.out.println(student.getStudentID()));


                    }catch(IOException | ClassNotFoundException exc){
                        exc.printStackTrace();
                    }

我还注意到,当我打开 .ser 文件时,里面只有一行。我假设这可能证明它实际上每次都在覆盖自己,因为我的理解是序列化文件中的对象应该有多少行。

任何人都可以帮助我了解我正在做什么导致文件覆盖自身而不是保留已添加的对象吗?

还有我的学生class供参考:

import java.io.Serializable;

public class Student implements Serializable{
    
    private static final long serialVersionUID = 1L;

    // Class Attributes
    private String studentID;
    private String rankings;
    private char personalityType;
    private String conflict;
    
    private String preferences;

    
    // Class Constructor

    public Student(String ID){
        this.studentID = ID;
    }
    
    public Student(String ID, String grades) {
        this.studentID = ID;
        grades = grades.trim();
        this.rankings = grades;
    }

    public Student(String ID, String ranking,char personality){
        this.studentID = ID;
        this.rankings = ranking;
        this.personalityType = personality;
    }
    
    // Accessor Methods
    public String getStudentID() {
        return this.studentID;
    }

    public String getRankings(){
        return this.rankings;
    }

    public String getPreferences(){
        return this.preferences;
    }

    public char getPersonalityType(){
        return this.personalityType;
    }

    public String getConflict(){
        return this.conflict;
    }

    //Modifier Methods

    public boolean setPreferences(String pref){
        this.preferences = pref;
        return true;
    }

    public boolean setGrades(String grades){
        this.rankings = grades;
        return true;
    }

    public boolean setPersonalityType(char pers){
        this.personalityType = Character.toUpperCase(pers);
        return true;
    }

    public boolean setConflict(String ids){
        this.conflict = ids;
        return true;
    }

    @Override

    public String toString(){
        return studentID + ";" + rankings + ";" + personalityType + ";" + conflict + ";" + preferences; 
    }
    

    
}

for(Student s: students){ 
    FileOutputStream fileOut = new FileOutputStream("C:/Users/Jaimee-Lee/Desktop/Advanced programming work/MilestoneOne/student.ser");
    ObjectOutputStream out = new ObjectOutputStream(fileOut);
    out.writeObject(s);
    out.close();
    fileOut.close();
}

您正在 for-loop 中创建一个新的 FileOutputStream,每次迭代都会覆盖旧信息。不要这样做,在循环之前创建流并在循环使用它:

FileOutputStream fileOut = new FileOutputStream("C:/Users/Jaimee-Lee/Desktop/Advanced programming work/MilestoneOne/student.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
for(Student s: students){ 
    out.writeObject(s);
}
out.close();

并在循环后关闭它。

您做错了几件事,首先是在写入每条记录时关闭和打开输出流,您想在写入数据之前打开它并在写入数据之后关闭它。

我查看了 .ser 文件 - 它似乎是二进制文件,因此如果您尝试打开它查看它,取决于您使用的编辑器类型,它可能会或可能不会显示交互信息。

这里是您想要执行的操作示例。 它在 java 8 上运行良好 ' 包 serTest;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class Student 
    implements Serializable{

    public String Name;
    public String Id;
    public String Major;
    public boolean  active;
    public int      years;
    
    Student(){
        Name    = "";
        Id      = "";
        Major   = "";
        active  = true;
        years   = 0;
        }
    
    Student(String Nam,String id,String major,boolean act,int yrs){
        Name    = Nam;
        Id      = id;
        Major   = major;
        active  = act;
        years   = yrs;
        }
    
    public static void main(String argv[]) {
        List<Student> myStudents = new ArrayList<Student>();
        myStudents.add(new Student("Mike","140","Art"       ,true,1));
        myStudents.add(new Student("Greg","142","Partying"  ,false,2));
        myStudents.add(new Student("Lori","145","Business"  ,true,3));
        myStudents.add(new Student("Burt","157","Eng"       ,true,4));
        Student.toFile("Students.ser",myStudents);
        
        List<Student> theStudents = Student.frFile("Students.ser");
        }
    
    static List<Student> frFile(String fSpec){
        
        List<Student>   Students = new ArrayList<Student>();
        try{
            FileInputStream fis = new FileInputStream(fSpec);
            ObjectInputStream ois = new ObjectInputStream(fis);
            while(fis.available() > 0 ){
                Students.add((Student) ois.readObject());
                System.out.println("Added");
                }

            System.out.println(Students.size()+" students read");
            Students.forEach(student -> System.out.println(student.Name));
            return Students;
            }
        catch(IOException | ClassNotFoundException exc){
            exc.printStackTrace();
            }
        return null;
        }
    
    static boolean toFile(String fSpec,List<Student> students) {
         try{
            FileOutputStream    fileOut =    new FileOutputStream(fSpec);
            ObjectOutputStream  out =       new ObjectOutputStream(fileOut);
            for(Student s: students){ 
                out.writeObject(s);;
                }
            out.close();
            fileOut.close();
            System.out.printf("Serialized data is saved in "+fSpec);
            }
        catch(IOException i){
            i.printStackTrace();
            return false;
            }
        return true;
        }
    }

`