首页 > 解决方案 > JavaFX:如何将 ObservableList 读写到文件中?

问题描述

我是编程新手,我想做的是/存储在 aObservableList中的数据,数据来自Student类,它们是字符串(名字和姓氏),而且我有一个TableView来显示数据。

这是我的代码:

学生班级:

import java.io.Serializable;
import javafx.beans.property.SimpleStringProperty;

public class Student implements Serializable {
    private SimpleStringProperty fname;
    private SimpleStringProperty lname;

    Student() {
        this("","");
    }

    Student(String fn, String ln) {
       this.fname = new SimpleStringProperty(fn);
       this.lname = new SimpleStringProperty(ln);
    }


    public void setFirstName(String f) {
        fname.set(f);
    }
    public String getFirstName() {
        return fname.get();
    }

    public void setLastName(String l) {
        lname.set(l);
    }
    public String getLastName() {
        return lname.get();
    }


    @Override
    public String toString() {
        return String.format("%s %s", getFirstName(), getLastName());
    }
}

这是我使用TextField输入数据的代码:

    @FXML
    ObservableList<Student> data = FXCollections.observableArrayList();

    //Just to input the data
    @FXML
    private void handleButtonAction(ActionEvent event) {

        if(!"".equals(txtFirstName.getText()) && !"".equals(txtLastName.getText())){
            data.add(
                    new Student(txtFirstName.getText(),
                                txtLastName.getText()
            ));
        }

        txtFirstName.clear();
        txtLastName.clear();

        // System.out.println(data);
    }

这就是问题所在...

读/写 ObservableList:

    @FXML
    private void HandleMenuSaveAction(ActionEvent event) {
         try {
            FileOutputStream f = new FileOutputStream(new File("saveStudentList.txt"));
            ObjectOutputStream o = new ObjectOutputStream(f);

            o.writeObject(data);
            o.close();
            f.close();

            System.out.println("File Saved Successfully.");

        } catch (FileNotFoundException ex) {
            System.err.println("Save: File not found.");
        } catch (IOException ex) {
            System.err.println("Save: Error initializing stream.");
            ex.printStackTrace();
        } 
    }

    @FXML
    private void HandleMenuLoadAction(ActionEvent event) {
         try {
            FileInputStream fi = new FileInputStream(new File("saveStudentList.txt"));
            ObjectInputStream oi = new ObjectInputStream(fi);

            data = (ObservableList) oi.readObject();

            System.out.println(data.toString());

            //Refresh the Table everytime we load data

            oi.close();
            fi.close();


        } catch (FileNotFoundException ex) {
            System.err.println("Load: File not found.");
        } catch (IOException ex) {
            System.err.println("Load: Error initializing stream.");
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        }
    }

这导致我java.io.NotSerializableException,有谁知道如何更改我的代码以使其正常工作?

标签: javafxioobservablelist

解决方案


为对象实现自定义序列化Student(参见https://stackoverflow.com/a/7290812/2991525)并将 的内容复制ObservableList到 aArrayList以创建可序列化列表:

public class Student implements Serializable {

    private void writeObject(ObjectOutputStream out)
            throws IOException {
        out.writeObject(getFirstName());
        out.writeObject(getLastName());
    }

    private void readObject(ObjectInputStream in)
            throws IOException, ClassNotFoundException {
        fname = new SimpleStringProperty((String) in.readObject());
        lname = new SimpleStringProperty((String) in.readObject());
    }

    ...
}

(反)序列化示例

ObservableList<Student> students = FXCollections.observableArrayList();

for(int i = 0; i < 100; i++) {
    students.add(new Student("Mark"+i, "Miller"+i));
}

ByteArrayOutputStream bos = new ByteArrayOutputStream();

// write list
try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {
    oos.writeObject(new ArrayList<>(students));
}

students = null; // make sure the old reference is no longer available

ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());

// read list
try (ObjectInputStream ois = new ObjectInputStream(bis)){
    students = FXCollections.observableList((List<Student>) ois.readObject());
}

System.out.println(students);

推荐阅读