在不是字符串或int的java中保存和加载对象

时间:2019-01-21 14:29:26

标签: java javafx serialization deserialization

我正在尝试在Java应用程序中保存和加载一个对象,该对象是另一个类的扩展。

我目前可以保存和加载当前类,但是我希望能够保存特定的对象,正如您在下面的代码中看到的那样,我已经声明了我的类Building并将其命名为TheBuilding,我想保存并加载此类。当前正在发生的事情是保存并加载BuildingGUI而不是特定对象

public class BuildingGUI extends Application implements Serializable{

private Building theBuilding;

public static void main(String[] args) {
    BuildingGUI Building2 = new BuildingGUI();
    try
      {
         //Create file output stream
         FileOutputStream fileOutStr =  new 
FileOutputStream("theBuilding.ser"); 
        //Create object output stream and write object
         ObjectOutputStream objOutStr = new 
ObjectOutputStream(fileOutStr);
         objOutStr.writeObject(Building2);
         //Close all streams
         objOutStr.close();
         fileOutStr.close();
         System.out.printf("Serialized data is saved in a file  - 
 theBuilding.ser");
      }catch(IOException exp)
      {
          System.out.println("Error IOException");
          exp.printStackTrace();
      }


BuildingGUI Building = null;{
try
  {
     FileInputStream fileInStr = new FileInputStream("theBuilding.ser");
     ObjectInputStream objInStr = new ObjectInputStream(fileInStr);
     Building = (BuildingGUI) objInStr.readObject();
     objInStr.close();
     fileInStr.close();
  }catch(IOException exp)
  {
      System.out.println("Error IOException");
     exp.printStackTrace();
     return;
  }catch(ClassNotFoundException cexp)
  {
     System.out.println("BuildingGUI class not found");
     cexp.printStackTrace();
     return;
  }
System.out.println(", theBuilding has been deserialized");

上面的代码通过保存BuildingGUI类文件然后再次加载来完成其预期的工作,但是我希望它保存一个特定的对象,该对象是私有Building theBuilding;

谢谢您的帮助

4 个答案:

答案 0 :(得分:1)

由于您声称自己的代码可以正常工作,因此我只是将其复制并粘贴到您原来的问题中。

您在正确的道路上,只是:

  1. 需要一种方法,当从您的main调用该方法时,它将采用BuildingGUI作为参数并将其序列化以存储在磁盘上。
  2. 需要一个方法,该方法在被调用时将文件名作为参数,反序列化文件并返回BuildingGUI。

您可以执行完全相同的操作,但对于Building类型的对象。只需将方法的参数更改为接受Building,而不是BuildingGUI


    //Method to serialize and store specific BuildingGUI
    public void buildingSaver(BuildingGUI building) throws IOException {
        //Create file output stream
        FileOutputStream fileOutStr = new FileOutputStream("theBuilding.ser");
        //Create object output stream and write object
        ObjectOutputStream objOutStr = new ObjectOutputStream(fileOutStr);
        objOutStr.writeObject(Building2);
        //Close all streams
        objOutStr.close();
        fileOutStr.close();
        System.out.printf("Serialized data is saved in a file  - theBuilding.ser");
    }

    //Method to deserialize BuildingGUI from file
    public BuildingGUI buildingLoader(String filename) throws IOException,
                                                    ClassNotFoundException{
        FileInputStream fileInStr = new FileInputStream(filename);
        ObjectInputStream objInStr = new ObjectInputStream(fileInStr);
        BuildingGUI building = (BuildingGUI) objInStr.readObject();
        objInStr.close();
        fileInStr.close();

        return building;
    }
  •   

    如果您有多种类型的对象需要怎么办?   店吗?

  •   

    您是否需要为所有这些方法编写单独的方法?

答案是

您可以有一个更通用的方法(也是static),该方法接受对象作为参数,如下所示:

    //parameter is Object, instead of Building
    public static void writeObjectToDisk(Object obj, String name) throws IOException {
        //Create file output stream
        FileOutputStream fileOutStr = new FileOutputStream(name);
        //Create object output stream and write object
        ObjectOutputStream objOutStr = new ObjectOutputStream(fileOutStr);
        objOutStr.writeObject(obj);
        //Close all streams
        objOutStr.close();
        fileOutStr.close();
        System.out.printf("Serialized data is saved in a file  - "+name);
    }

    public static Object objectLoader(String filename) throws IOException,
                                                      ClassNotFoundException{
        FileInputStream fileInStr = new FileInputStream(filename);
        ObjectInputStream objInStr = new ObjectInputStream(fileInStr);
        Object obj = (Object) objInStr.readObject();
        objInStr.close();
        fileInStr.close();

        return obj;
    }

要从Building内部获取BuildingGUI,您将需要一个访问器方法:

public class BuildingGUI extends Application implements Serializable{

    private Building theBuilding;

    public Building getBuilding(){
        return this.theBuilding;
    }

    /*other code..*/
}

最后,在您的main方法中:

public static void main(String[] args) {

    //initialize BuildingGUI object and get the Building object
    BuildingGUI building2 = new BuildingGUI();
    Building myBuilding = building2.getBuilding();

    //we serialize the Building, by casting it to (Object) and feeding it to the method
    try{
        someClass.writeObjectToDisk((Object)myBuilding);
    }
    catch(IOException ioe){
        ioe.printStackTrace();
    }

    Building myBuilding2 = null;
    BuildingGUI buildingGUI = null;
    //now for deserializing
    try{
        //We cast to appropriate type, because method returns 'Object'
        myBuilding2 = (Building)objectLoader("building.ser");
        buildingGUI = (BuildingGUI)objectLoader("buildingGUI.ser");
    }
    catch(IOException ioe){
        ioe.printStackTrace();
    }
    catch(ClassNotFoundException cnfe){
        cnfe.printStackTrace();
    }
}

最终通知: 如果初始化Building类内部的BuildingGUI对象引用。然后,在序列化BuildingGUI时,也将隐式序列化Building对象引用。因此,当您反序列化 BuildingGUI时,您也可以访问Building。我将添加最后一个范例。

public class BuildingGUI extends Application implements Serializable{

    private Building theBuilding = new Building(); <-- we initialize it

    public Building getBuilding(){
        return this.theBuilding;
    }
}

public static void main(String[] args) {

    //initialize BuildingGUI object and get the Building object
    BuildingGUI building2 = new BuildingGUI();

    //we serialize the Building, by casting it to (Object) and feeding it to the method
    try{
        someClass.writeObjectToDisk((Object)building2);
    }
    catch(IOException ioe){
        ioe.printStackTrace();
    }

    BuildingGUI buildingGUI = null;
    //now for deserializing JUST THE BUILDINGGUI
    try{
        //We cast to appropriate type, because method returns 'Object'
        buildingGUI = (BuildingGUI)ObjectLoader("buildingGUI.ser");
    }
    catch(IOException ioe){
        ioe.printStackTrace();
    }
    catch(ClassNotFoundException cnfe){
        cnfe.printStackTrace();
    }

    //You can get the building this way
    Building myBuilding = buildingGUI.getBuilding();
}

答案 1 :(得分:1)

在您的main()方法中,您有一个名为Building2的局部变量,它是类BuildingGUI的实例:

BuildingGUI Building2 = new BuildingGUI();

几行后,您正在将该对象写入文件:

objOutStr.writeObject(Building2);

因此,这就是您的程序向文件写入BuildingGUI对象的原因。

您的类BuildingGUI具有一个声明的theBuilding类型的名为Building的成员变量。如果您只想将Building对象写入文件,则必须将写入对象的行更改为只写入该对象:

// Write the Building object that is contained
// in the BuildingGUI object to the file
objOutStr.writeObject(Building2.theBuilding);

但是,还缺少其他内容:您没有在代码中的任何地方初始化成员变量theBuilding,因此它将被设置为默认值null。您需要正确初始化它,例如,将第3行更改为:

private Building theBuilding = new Building();

请注意,这仅是一个示例,您没有向我们展示类Building,所以我不知道它是否有一个不带参数的构造函数,使您可以像这样实例化它,或者您是否需要将参数传递给构造函数或以另一种方式实例化对象。

您还必须更改从文件加载数据的代码,因为您要在其中加载Building对象,而不是BuildingGUI对象。

答案 2 :(得分:0)

我不确定您是否很好地理解了您的问题,但我会尝试一下。 第一个问题:Building类是Serializable类吗?

如果是这样,这是一个好的开始。然后,您现在正在做的是从静态上下文(在main方法中)调用序列化代码,而您正在做的事情:

objOutStr.writeObject(Building2);

如此有效地,对象BuildingGUI被按预期方式序列化了。 如果要序列化Building对象,则需要使用getter对其进行访问,例如:

public Building getBuilding() {
  return theBuilding;
}

然后将您的代码替换为:objOutStr.writeObject(Building2.getBuilding());

然后,在进行反序列化时,您将拥有一个Building类Object。

答案 3 :(得分:-1)

您可以使用:杰克逊。这是一个映射器,它可以将对象转换为json格式。然后,您将能够将此json字符串加载到特定的给定对象中