Java - 如何将文件读入对象的ArrayList?

3

我想创建一个学生的 ArrayList 并将其保存到文件以供以后使用。我成功写入了它,但是当我将其读回到 ArrayList 时,我只有一个对象。

public class Student implements Serializable{
public String fname, lname, course;
int section;
private static final long serialVersionUID = 1L;

public static ArrayList<Student> students = getStudent();

public Student() {
}

public Student(String fname, String lname, String course, int section){
    this.fname = fname;
    this.lname = lname;
    this.course = course;
    this.section = section;
}
public static void addStudent(){
    String fname = GetInput.getInput("Enter the First Name: ");
    String lname = GetInput.getInput("Enter the Last Name: ");
    String course = GetInput.getInput("Enter the Course: ");
    String S_section = GetInput.getInput("Enter the section: ");
    int section = Integer.parseInt(S_section);
    Student student = new Student(fname, lname, course, section);  
    students.add(student); 
    System.out.println("Writing to file...");
    try {
        writeToFile(student);
    } catch (FileNotFoundException ex) {
        System.out.println(ex.getMessage());
    } catch (IOException ex) {
        System.out.println(ex.getMessage());
    }
}

public static ArrayList<Student> getStudent(){
    try{
        FileInputStream fis = new FileInputStream("C:\\students.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        ArrayList<Student> students1 = (ArrayList<Student>) ois.readObject();

        ois.close();

        return students1;
    } catch( ClassNotFoundException | IOException ex){
        System.out.println(ex.getMessage());
        return null;
    }
}
public static void listStudent(ArrayList<Student> students){
    System.out.println("View the Records in the Database:");
    for(Student student: students){
        System.out.println("Name: " + student.fname + " " + student.lname);
        System.out.println("Course: " + student.course);
        System.out.println("Section: " + student.section);
        System.out.println();
    }
}

static void writeToFile(Student student) throws FileNotFoundException, IOException{
    String path = "C:\\students.ser";
    FileOutputStream fos = new FileOutputStream(path, true);
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(student);
    oos.close();
    System.out.println("New Record has been written!");
}

当我通过调用getStudent()读取文件并通过listStudent()输出时,只有一个记录的文件。 请帮帮我!非常感谢。
编辑: 我试过将arraylist写入文件并将其读入arraylist。我会向您展示我是如何做到这一点的。 首先,我将arraylist写入文件:
public static ArrayList<Student> students = new ArrayList<>();

public static void addStudent(){
    Student student = new Student(fname, lname, course, section);  
    students.add(student); 
    System.out.println("Writing to file...");
    try {
        writeToFile(students);
    }catch...
}

static void writeToFile(ArrayList<Student> students) throws FileNotFoundException, IOException{
    String path = "C:\\students.ser";
    FileOutputStream fos = new FileOutputStream(path, true);
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(students);
    oos.close();
    System.out.println("New Record has been written!");

然后我阅读了学生档案:

public static ArrayList<Student> getStudent(){
    try{
        FileInputStream fis = new FileInputStream("C:\\students.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        ArrayList<Student> students1 = (ArrayList<Student>) ois.readObject();
        ois.close();
        return students1;
    } catch( ClassNotFoundException | IOException ex){
        System.out.println(ex.getMessage());
        return null;
    }
}

我发现随着文件大小的增长,文件中有很多对象。但是在读取后,我只看到了一个对象,那就是我最初写入文件的对象。


2
你似乎只写了一个学生到文件中,所以读取时只能读入一个。 - Hovercraft Full Of Eels
感谢您的评论。我注意到了,但是我将新对象附加到旧文件中,因此从技术上讲,我的文件中有一堆对象。FileOutputStream fos = new FileOutputStream(path, true); - TomNg
3个回答

3
我建议您更新学生类的序列化代码(因为您没有序列化静态 students),操作步骤如下 -
// This controls how Student(s) will be written.
private void writeObject(ObjectOutputStream oos)
    throws IOException {
  oos.defaultWriteObject();
  // How many students we're tracking.
  oos.writeInt(students.size());
  for (Student student : students) {
    oos.writeObject(student);
  }
  System.out.println("session serialized");
}

// Control how we read in Student(s).
private void readObject(ObjectInputStream ois)
    throws IOException, ClassNotFoundException {
  ois.defaultReadObject();
  // how many Students to read.
  int size = ois.readInt();
  for (int i = 0; i < size; i++) {
    Student s = (Student) ois.readObject();
    students.add(s);
  }
  System.out.println("session deserialized");
}

非常感谢您的回答,我尝试添加了您的代码,但是在listStudent()方法的for循环中出现了NullPointerException异常。我认为这是因为getStudent()方法返回了空值。有什么建议吗? - TomNg

0

你正在编写一个单独的学生对象:

oos.writeObject(student);

但是正在尝试获取一个ArrayList:

 ArrayList<Student> students1 = (ArrayList<Student>) ois.readObject();

实际上,我曾尝试将ArrayList写入文件并成功了,我可以在文件中看到记录。然而,当我从文件中读取数据时,我会得到空异常。 - TomNg

0
你在评论中说:
“感谢您的评论。我注意到了,但是我将新对象附加到旧文件中,因此从技术上讲,我的文件中有一堆对象。FileOutputStream fos = new FileOutputStream(path,true);”
虽然这在技术上确实会追加到文件的末尾,并且在文本文件中非常有效,但我真的不认为这对序列化会起作用或者效果很好。我猜想,要使用序列化进行追加,您首先必须从文件中读取所有对象,然后通过序列化机制写入而不是追加它们。如果我是您,我会重新编写您的输入和输出代码。

编辑
我担心你把太多不同的东西都塞进了一个类里,这会导致程序混乱且难以调试。以下是一些通用建议,可以帮助你整理这个任务:

  • 首先创建一个名为Student的类--你已经做到了--但要将其作为纯学生类,具有私有的名字、姓氏、部分和课程字段,以及这些字段的getter和setter(你需要这些),适当的构造函数(我认为你已经掌握了这个)。
  • 给它一个体面的public String toString()方法,返回一个包含对象字段值的字符串。
  • 从Student中获取所有其他内容,所有静态方法,所有ArrayLists,任何用于写入或读取文件的代码。
  • 创建另一个类,比如叫做StudentCollection。
  • 给它一个私有的非静态ArrayList<Student>字段,比如叫做students。
  • 给它一个addStudent(Student student)方法,允许外部类向该类添加学生对象。
  • 给它一个public String toString()方法,返回列表的toString(),即return students.toString();
  • 给它一个public void readFromFile(File file)方法,使用序列化从文件中读取ArrayList<Student>
  • 给它一个public void writeToFile(File file)方法,使用序列化将ArrayList<Student>写入文件。
  • 最后,创建一个TestStudent类,它只有一个方法,一个公共的静态void main方法。
  • 在main中,创建一个StudentCollection对象。
  • 使用你的addStudent(...)方法填充它。
  • 创建一个File对象并调用writeToFile(...),传入你的文件。
  • 然后测试从同一文件读取...

例如,主方法看起来几乎像下面的代码。请注意,为了证明这个方法可行,我创建了一个简化版的学生类,只有两个参数,用于名字的姓和名。你的代码显然会有更多的参数。
import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class StudentTest {
   private static final String DATA_FILE_PATH = "myFile.dat";

   public static void main(String[] args) {
      Student[] students = {new Student("John", "Smith"),
            new Student("Mike", "Barnes"),
            new Student("Mickey", "Mouse"),
            new Student("Donald", "Duck")};

      // create our collection object
      StudentCollection studentColl1 = new StudentCollection();

      // print out that it currently is empty
      System.out.println("studentColl1: " + studentColl1);

      // Add Student objects to it
      for (Student student : students) {
         studentColl1.addStudent(student);
      }

      // show that it is now full
      System.out.println("studentColl1: " + studentColl1);

      // create a file
      File myFile = new File(DATA_FILE_PATH);

      // write out our collection to file on disk
      studentColl1.writeToFile(myFile);

      // create another collection object 
      StudentCollection studentColl2 = new StudentCollection();

      // show that it is empty
      System.out.println("studentColl2: " + studentColl2);

      // read the list back into the new StudentCollection object
      File myFile2 = new File(DATA_FILE_PATH);
      studentColl2.readFromFile(myFile2);

      // add a few more Student's:
      studentColl2.addStudent(new Student("Stack", "Overflow"));
      studentColl2.addStudent(new Student("Donald", "Trump"));

      // show the result
      System.out.println("studentColl2: " + studentColl2);
   }
}

我仍然卡在这个问题上,我以为这对我来说是一个很容易的小Java项目。顺便问一下,你能给我一个提示如何从文件中读取所有对象吗? - TomNg
@coderkisser:请更新你的问题——展示你最新尝试读取和写入所有内容的代码,以及你在这段代码中遇到的最新问题。请不要更改原始问题中的代码和文本,因为那将使我们当前的大部分答案无效,而是在现有问题的底部添加附录,然后当你重新提出问题时,请通知任何回答或评论你的人。 - Hovercraft Full Of Eels
谢谢您的建议。我刚刚更新了我的问题。 - TomNg
@coderkisser:请查看我的回答编辑。请注意,如果我的任何建议与您的任务说明相违背,请将所有说明作为问题的编辑发布。 - Hovercraft Full Of Eels
非常感谢您提供如此详细的指导。看起来现在可以工作了。我想我应该将事物分开处理。 - TomNg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接