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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20086784/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 23:01:38  来源:igfitidea点击:

Java - How to read file into ArrayList of Objects?

javaarraylist

提问by TomNg

I wanna make an ArrayListof Student and save it to a file for later use. I successfully wrote it but when I read it back to ArrayList, I have only one Object.

我想制作一个ArrayList学生并将其保存到文件中以备后用。我成功地写了它,但是当我读回它时ArrayList,我只有一个 Object.

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!");
}

When I read file by calling getStudent()and print it out by listStudent()I have only one record of the file.

当我通过调用读取文件getStudent()并将其打印出来时,listStudent()我只有一个文件记录。

Please help me! Much appreciate.

请帮我!非常感谢。

EDIT

编辑

I had tried writing an arraylistto file and read it into arraylist. I'll show you how I did that. Firstly, I write arraylistto file:

我曾尝试编写一个arraylistto 文件并将其读入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!");

And then I read student file:

然后我读了学生档案:

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;
    }
}

I can see that in the file I have many objects as the file size keep growing. But I only one object after read it, which is my very first object I wrote to file.

我可以看到在文件中我有很多对象,因为文件大小不断增长。但是我读完后只有一个对象,这是我写入文件的第一个对象。

采纳答案by Hovercraft Full Of Eels

You state in comment:

你在评论中说:

Thanks for your comment. I noticed that, however I appended the new object to the old file, so technically I have bunch of objects in my file. FileOutputStream fos = new FileOutputStream(path, true);

谢谢你的评论。我注意到,但是我将新对象附加到旧文件中,因此从技术上讲,我的文件中有一堆对象。FileOutputStream fos = new FileOutputStream(path, true);

While this technically does append to the end of a file, and works great with text files, I really don't think that this will work or work well with serialization. I would guess that to append with serialization, you'd first have to read all the objects in from the file, and then write without appending all of them via the serialization mechanism. I would re-write your input and output code if I were you.

虽然这在技术上确实附加到文件的末尾,并且适用于文本文件,但我真的不认为这将适用于或适用于序列化。我猜想附加序列化,您首先必须从文件中读取所有对象,然后写入而不通过序列化机制附加所有对象。如果我是你,我会重写你的输入和输出代码。



Edit
I fear that you've got too much disparate stuff all crammed into one single class, making for a messy and hard to debug program. Some general recommendations to help clean up this assignment:

编辑
我担心您将太多不同的东西都塞进一个类中,从而导致程序混乱且难以调试。一些有助于清理此作业的一般建议:

  • First create a class called Student -- you've done this -- but make it a pure Student class with privatefirst name, last name, section and course fields, getters and setters for those fields (you need these), appropriate constructors (I think you've got this).
  • Give it a decent public String toString()method that returns a String that holds the values of the object's fields.
  • Get everything else out of Student, all the static methods, all the ArrayLists, any code for writing to or reading from files.
  • Create another class, say called StudentCollection
  • Give it a private non-static ArrayList<Student>field, say called students.
  • Give it an addStudent(Student student)method that allows outside classes to add Student objects to this class.
  • Give it a public String toString()method that returns the list's toString(), i.e., return students.toString();.
  • Give it a public void readFromFile(File file)method that uses serialization to read an ArrayList<Student>from a File.
  • Give it a public void writeToFile(File file)method that uses serialization to write an ArrayList<Student>to a File.
  • Finally, create a TestStudent class that has only one method, a public static void main method.
  • In main, create a StudentCollection object.
  • Fill it with Students using your addStudent(...)method.
  • Create a File object and call writeToFile(...)passing in your File.
  • Then test reading from the same file...
  • 首先创建一个名为 Student 的类——你已经完成了这个——但是让它成为一个纯 Student 类,带有私有的名字、姓氏、部分和课程字段、这些字段的 getter 和 setter(你需要这些)、适当的构造函数(我想你有这个)。
  • 给它一个体面的public String toString()方法,它返回一个包含对象字段值的字符串。
  • 从 Student 中获取所有其他内容,所有静态方法,所有 ArrayList,以及用于写入或读取文件的任何代码。
  • 创建另一个类,比如说叫做 StudentCollection
  • 给它一个私有的非静态ArrayList<Student>字段,比如说叫学生。
  • 给它一个addStudent(Student student)允许外部类向这个类添加 Student 对象的方法。
  • 给它一个public String toString()返回列表的 toString() 的方法,即return students.toString();.
  • 给它一个public void readFromFile(File file)使用序列化ArrayList<Student>从文件中读取 的方法。
  • 给它一个public void writeToFile(File file)使用序列化将 an 写入ArrayList<Student>文件的方法。
  • 最后,创建一个只有一个方法的 TestStudent 类,一个 public static void main 方法。
  • 在 main 中,创建一个 StudentCollection 对象。
  • 使用您的addStudent(...)方法填写学生。
  • 创建一个 File 对象并调用writeToFile(...)传入您的 File。
  • 然后测试从同一个文件读取...


For example, the main method could look almost like the code below. Note though that in my test case to prove that this works, I created a simplifiedStudent class, one that only took 2 parameters, for first and last names. Your code obviously will take more parameters.

例如,main 方法可能看起来几乎像下面的代码。请注意,在我的测试用例中,为了证明这是有效的,我创建了一个简化的Student 类,该类只采用 2 个参数,用于名字和姓氏。您的代码显然将采用更多参数。

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);
   }
}

回答by Elliott Frisch

I would suggest you update your Serialization code for your Student class (because you're not Serializing your static students) as follows -

我建议你更新你的 Student 类的序列化代码(因为你没有序列化你的 static 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");
}

回答by user3001267

You're writing a single Student object:

您正在编写一个 Student 对象:

oos.writeObject(student);

But are trying to get an ArrayList:

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

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