我可以使用 FileChooser (javafx) 将序列化对象保存在文件中吗?

Posted

技术标签:

【中文标题】我可以使用 FileChooser (javafx) 将序列化对象保存在文件中吗?【英文标题】:Can I save a serialized Object in a File using FileChooser (javafx)? 【发布时间】:2018-01-15 13:56:52 【问题描述】:

标题非常不言自明。我想保存序列化的“spiel” 使用文件选择器作为“name.ser”文件。我还想加载文件并将其返回给我的控制器。我不知道如何连接 objectoutputstream 和 filechooser。

public class Speicher 

    public void spielstandSpeichern(Spiel spiel, String name)  // Save File

    try

        FileChooser fs = new FileChooser();

        fs.setInitialDirectory(new File("/Saves"));
        fs.setTitle("Spiel speichern");

        fs.getExtensionFilters().addAll(
                new FileChooser.ExtensionFilter("Ser", ".ser")
        );

        //File file =



        FileOutputStream fos = new FileOutputStream("Saves/save1.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        oos.writeObject(spiel);

        oos.close();
        fos.close();
    
    catch(IOException e) 
        e.printStackTrace();
    



public Spiel spielstandLaden()   // Load File

    Spiel spiel = null;

    try
        FileInputStream fis = new FileInputStream("Saves/save1.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);

        spiel = (Spiel) ois.readObject();

        ois.close();
        fis.close();
    
    catch(ClassNotFoundException e) 
        e.printStackTrace();
    
    catch(IOException e) 
        e.printStackTrace();
    

    return spiel;

提前致谢:)

【问题讨论】:

【参考方案1】:

您可以在 FileChooser 实例上分别使用showSaveDialogshowOpenDialog 来获取文件句柄对象以进行加载和保存。您可以在 FileInputStream 和 FileOutputStream 构造函数中使用此文件句柄对象。

【讨论】:

谢谢你,它似乎正在工作。但我刚刚意识到我无法将对象“Spiel”作为一个整体加载,因为 Spiel 中的某些类包含图像。论文图像未序列化。你知道我该如何解决这个问题吗? 在 Java 中,只有实现了java.io.Serializable 的对象才能完成对象序列化(大多数基本类型,如 String、Integer 等)。请确保必填字段是可序列化的并且没有transient 修饰符。要回答您的问题,您应该提供“Spiel”类定义的 sn-p。 我的 sn-p 在下面的答案中:)【参考方案2】:

感谢您在这方面帮助我 :) 我正在使用 MVC 架构。所以以下是我的课“Spiel”。基本上是我模特的妈妈。模型中的所有其他类都住在这里。 “Spiel”本身由“Fassade”和“Speicher”(保存/加载 Spiel 的类)处理,这是唯一不在“Spiel”内部的模型类。

“Spiel”及其下模型中的每个类都实现了可序列化。但是在某些类中,我在第一次初始化它们时会创建 new Image()。加载保存的“Spiel”时,JavaFX 无法重新创建图像,因为它们没有被序列化。

你知道我该如何解决这个问题,以便我可以保存/加载游戏吗?

public class Spiel implements Serializable 

// Attribute
private static final long serialVersionUID = 16L;

private Spielzug spielzug;
private ArrayList<Spieler> spieler;

private Map map;

private Deck deck;
private Ablage ablage;
private OffeneKarten offeneKarten;

private ArrayList<RoutenBP> routenBP;
private ArrayList<StadtBP> stadtBP;
private AlleProvinzenBP alleProvinzenBP;

// Konstruktor
public Spiel(ArrayList<Spieler> spieler) 

    this.spieler = spieler;

    map = new Map();

    deck = new Deck();
    ablage = new Ablage(map);
    ablage.kartenVerteilen(deck.getDeck());
    offeneKarten = new OffeneKarten(deck);

    spielzug = new Spielzug(spieler.get(0));

    bpInitialisieren();


// Methoden

// Initialisierung
private void bpInitialisieren()

    //Routen BP initialisieren
            routenBP = new ArrayList<RoutenBP>();
            ArrayList<Image> routenImg = new ArrayList<Image>();

            routenImg.add(new Image("Bilder/bp_S5_2.png"));
            routenImg.add(new Image("Bilder/bp_S5_1.png"));
            RoutenBP routenbp_1 = new RoutenBP(5, 2, 2, "Du brauchst eine geschlossene Route der Laenge 5, um dieses Bonusplaettchen zu erhalten.", routenImg);
            routenBP.add(routenbp_1);

            routenImg.clear();
            routenImg.add(new Image("Bilder/bp_S6_3.png"));
            routenImg.add(new Image("Bilder/bp_S6_2.png"));
            routenImg.add(new Image("Bilder/bp_S6_1.png"));
            RoutenBP routenbp_2 = new RoutenBP(6, 3, 3, "Du brauchst eine geschlossene Route der Laenge 6, um dieses Bonusplaettchen zu erhalten.", routenImg);
            routenBP.add(routenbp_2);

            routenImg.clear();
            routenImg.add(new Image("Bilder/bp_S7_4.png"));
            routenImg.add(new Image("Bilder/bp_S7_3.png"));
            routenImg.add(new Image("Bilder/bp_S7_2.png"));
            routenImg.add(new Image("Bilder/bp_S7_1.png"));
            RoutenBP routenbp_3 = new RoutenBP(6, 4, 4, "Du brauchst eine geschlossene Route der Laenge 7, um dieses Bonusplaettchen zu erhalten.",routenImg);
            routenBP.add(routenbp_3);

            //Stadt BP initialisieren
            stadtBP = new ArrayList<StadtBP>();
            ArrayList<Image> stadtbpImg = new ArrayList<Image>();

            stadtbpImg.add(new Image("Bilder/bp_lilaP_3.png"));
            stadtbpImg.add(new Image("Bilder/bp_lilaP_2.png"));
            stadtbpImg.add(new Image("Bilder/bp_lilaP_1.png"));
            ArrayList<Karte> benoetigteStaedte = new ArrayList<Karte>();
            benoetigteStaedte.add(map.getStadt(3));
            benoetigteStaedte.add(map.getStadt(4));
            benoetigteStaedte.add(map.getStadt(10));
            StadtBP stadtbp_1 = new StadtBP(benoetigteStaedte, 3, 3, "Du brauchst in Freiburg, Mannheim und Carlsruhe ein Haus, um dieses Bonusplaettchen zu erhalten.",stadtbpImg);
            stadtBP.add(stadtbp_1);

            stadtbpImg.clear();
            stadtbpImg.add(new Image("Bilder/bp_blauP_3.png"));
            stadtbpImg.add(new Image("Bilder/bp_blauP_1.png"));
            stadtbpImg.add(new Image("Bilder/bp_blauP_2.png"));
            benoetigteStaedte.clear();
            benoetigteStaedte.add(map.getStadt(1));
            benoetigteStaedte.add(map.getStadt(21));
            benoetigteStaedte.add(map.getStadt(6));
            StadtBP stadtbp_2 = new StadtBP(benoetigteStaedte, 3, 3, "Du brauchst in Basel, Zuerich und Innsbruck ein Haus, um dieses Bonusplaettchen zu erhalten.",stadtbpImg);
            stadtBP.add(stadtbp_2);

            stadtbpImg.clear();
            stadtbpImg.add(new Image("Bilder/bp_gruenP_3.png"));
            stadtbpImg.add(new Image("Bilder/bp_gruenP_2.png"));
            stadtbpImg.add(new Image("Bilder/bp_gruenP_1.png"));
            benoetigteStaedte.clear();
            benoetigteStaedte.add(map.getStadt(17));
            benoetigteStaedte.add(map.getStadt(18));
            benoetigteStaedte.add(map.getStadt(19));
            StadtBP stadtbp_3 = new StadtBP(benoetigteStaedte, 3, 3, "Du brauchst in Sigmaringen, Stuttgart und Ulm ein Haus, um dieses Bonusplaettchen zu erhalten.",stadtbpImg);
            stadtBP.add(stadtbp_3);

            stadtbpImg.clear();
            stadtbpImg.add(new Image("Bilder/bp_rotP_4.png"));
            stadtbpImg.add(new Image("Bilder/bp_rotP_3.png"));
            stadtbpImg.add(new Image("Bilder/bp_rotP_2.png"));
            benoetigteStaedte.clear();
            benoetigteStaedte.add(map.getStadt(2));
            benoetigteStaedte.add(map.getStadt(8));
            benoetigteStaedte.add(map.getStadt(14));
            benoetigteStaedte.add(map.getStadt(16));
            StadtBP stadtbp_4 = new StadtBP(benoetigteStaedte, 4, 3, "Du brauchst in Budweis, Pilsen, Linz und Salzburg ein Haus, um dieses Bonusplaettchen zu erhalten.",stadtbpImg);
            stadtBP.add(stadtbp_4);

            stadtbpImg.clear();
            stadtbpImg.add(new Image("Bilder/bp_beigeP_5.png"));
            stadtbpImg.add(new Image("Bilder/bp_beigeP_4.png"));
            stadtbpImg.add(new Image("Bilder/bp_beigeP_3.png"));
            stadtbpImg.add(new Image("Bilder/bp_beigeP_2.png"));
            benoetigteStaedte.clear();
            benoetigteStaedte.add(map.getStadt(0));
            benoetigteStaedte.add(map.getStadt(5));
            benoetigteStaedte.add(map.getStadt(7));
            benoetigteStaedte.add(map.getStadt(11));
            benoetigteStaedte.add(map.getStadt(12));
            benoetigteStaedte.add(map.getStadt(13));
            benoetigteStaedte.add(map.getStadt(15));
            benoetigteStaedte.add(map.getStadt(20));
            StadtBP stadtbp_5 = new StadtBP(benoetigteStaedte, 5, 4, "Du brauchst in Augsburg, Ingolstadt, Kempten, Münschen, Nürnberg, Passau, Regensburg und Würzburg ein Haus, um dieses Bonusplaettchen zu erhalten.",stadtbpImg);
            stadtBP.add(stadtbp_5);

            //Alle Provinzen BP initialisieren
            ArrayList<Image> alleProvImg = new ArrayList<Image>();
            alleProvImg.add(new Image("Bilder/bp_alleP_6.png"));
            alleProvImg.add(new Image("Bilder/bp_alleP_5.png"));
            alleProvImg.add(new Image("Bilder/bp_alleP_4.png"));
            alleProvImg.add(new Image("Bilder/bp_alleP_3.png"));
            alleProvinzenBP = new AlleProvinzenBP(map.getProvinzen(), 6,4, "Du brauchst in min. einer Stadt jeder Provinz ein Haus, um dieses Bonusplaettchen zu erhalten.",alleProvImg);


// Methoden

/**
 * Nimmt den jetzigen Spieler entgegegen und uebergibt den naechsten.
 *
 * @param spieler der jetzt fertig ist
 * @return spieler der jetzt dran ist
 */
public void naechsterSpieler() 

    int idx = spielzug.getAktuellerSpieler().getSpielerNr();

    if( idx == spieler.size() ) 
        idx = 0;
    

    System.out.println("SPIEL: Anzahl spieler: "+spieler.size());
    spielzug.setAktuellerSpieler(spieler.get(idx));

    System.out.println("SPIEL: nächster Spieler ist "+spieler.get(idx).getName()+" mit SpielerNr "+ spieler.get(idx).getSpielerNr());


public void bpVergeben()

    for(RoutenBP rbp : routenBP)
    
        if(rbp.bedingungErfuellt(spielzug.getAktuellerSpieler().getRoute().getStaedte(), spielzug))
        
            // gibt BP an Spieler
            spielzug.getAktuellerSpieler().getRoutenBP().add(rbp);
            // gibt Punkte für BP an Spieler
            int p = spielzug.getAktuellerSpieler().getPunkte()
                        + rbp.getPunkte(spielzug.getPhase());
            spielzug.getAktuellerSpieler().setPunkte(p);
        
    

    for(StadtBP sbp : stadtBP)
    
        if(sbp.bedingungErfuellt(spielzug.getAktuellerSpieler().getRoute().getStaedte(), spielzug))
        
            // gibt BP an Spieler
            spielzug.getAktuellerSpieler().getStadtBP().add(sbp);
            // gibt Punkte für BP an Spieler
            int p = spielzug.getAktuellerSpieler().getPunkte()
                        +sbp.getPunkte(spielzug.getPhase());
            spielzug.getAktuellerSpieler().setPunkte(p);
        
    

    if(alleProvinzenBP.bedingungErfuellt(spielzug.getAktuellerSpieler().getRoute().getStaedte(), spielzug))
    
        // gibt BP an Spieler
        spielzug.getAktuellerSpieler().setAlleProvinzBP(alleProvinzenBP);
        // gibt Punkte für BP an Spieler
        int p = spielzug.getAktuellerSpieler().getPunkte()
                    +alleProvinzenBP.getPunkte(spielzug.getPhase());
        spielzug.getAktuellerSpieler().setPunkte(p);
    


public void kutscheAktualisieren() 

    if(spielzug.getAktuellerSpieler().getKutsche().bedingungErfuellt(spielzug.getAktuellerSpieler().getRoute().getStaedte(), spielzug))
    
        int p = spielzug.getAktuellerSpieler().getPunkte()
                    + spielzug.getAktuellerSpieler().getKutsche().getPunkte(spielzug.getPhase());
        spielzug.getAktuellerSpieler().setPunkte(p);
    

public void hauspunkteVergeben()

    if(spielzug.getAktuellerSpieler().getHaeuser()
            .bedingungErfuellt(spielzug.getAktuellerSpieler().getRoute().getStaedte(), spielzug))
    
        int p = spielzug.getAktuellerSpieler().getPunkte()
                    + spielzug.getAktuellerSpieler().getHaeuser().getPunkte(spielzug.getPhase());
        spielzug.getAktuellerSpieler().setPunkte(p);
    






// Setter und Getter FUnktionen


public Spielzug getSpielzug() 
    return spielzug;


public void setSpielzug(Spielzug spielzug) 
    this.spielzug = spielzug;


public ArrayList<Spieler> getSpieler() 
    return spieler;


public void setSpieler(ArrayList<Spieler> spieler) 
    this.spieler = spieler;


public Map getMap() 
    return map;


public void setMap(Map map) 
    this.map = map;


public Deck getDeck() 
    return deck;


public void setDeck(Deck deck) 
    this.deck = deck;


public Ablage getAblage() 
    return ablage;


public void setAblage(Ablage ablage) 
    this.ablage = ablage;


public OffeneKarten getOffeneKarten() 
    return offeneKarten;


public void setOffeneKarten(OffeneKarten offeneKarten) 
    this.offeneKarten = offeneKarten;


public ArrayList<RoutenBP> getRoutenBP() 
    return routenBP;


public ArrayList<StadtBP> getStadtBP() 
    return stadtBP;


public AlleProvinzenBP getAlleProvinzenBP() 
    return alleProvinzenBP;

【讨论】:

我认为参与序列化的类应该定义一个非参数构造函数。您使用的是什么图像对象。你的问题是基于 javafx,所以我假设它是 javafx.scene.image.Image,它没有实现 Serializable。如果是这样,请尝试使用不同的类,您可以从中创建 javafx Image 对象。如果需要序列化的全部威力,可以实现:private void writeObject(ObjectOutputStream out) throws IOException; private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException; 来增强正常进程。 所以我可以实现一个扩展 Image 并实现 Serialziable 的类“图片”?很有帮助,谢谢 我没有对此进行测试,但我有疑问。整个类层次结构需要是可序列化的。您可以尝试使用对象组合创建一个带有 Image 类型的瞬态字段和一个捕获图像路径的 String 字段的 Picture 类(实现 Serializable)。在您的 getImage 方法中,您可以使用字符串路径创建 Image 对象(如果为 null)。

以上是关于我可以使用 FileChooser (javafx) 将序列化对象保存在文件中吗?的主要内容,如果未能解决你的问题,请参考以下文章

javafx如何导入文件

Java开发桌面程序学习——文件选择器和目录选择器的使用

javafx 场景生成器 2.0 中的文件选择器在哪里?我找不到它

FileChooser 的字体颜色

Kivy - 更改 FileChooser 默认位置

Kivy 弹出 Filechooser 传递变量(选择)