Сохранение и загрузка объекта в Java, который не является строкой или int - PullRequest
0 голосов
/ 21 января 2019

Я пытаюсь сохранить и загрузить объект в моем 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 с последующей его загрузкой, но я хочу, чтобы он сохранилконкретный объект, который является частным зданием theBuilding;

Спасибо за любую помощь

Ответы [ 4 ]

0 голосов
/ 21 января 2019

Вы можете использовать: Джексон.Это картограф, он может преобразовать объект в формат json.Затем вы сможете загрузить эту строку JSON в конкретный данный объект

0 голосов
/ 21 января 2019

В вашем методе 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.

0 голосов
/ 21 января 2019

Я не уверен, что понимаю ваш вопрос хорошо, но я попробую. Первый вопрос: Building класс Serializable?

Если это так, это хорошее начало. Тогда то, что вы делаете прямо сейчас, это вызов кода Serialize из статического контекста (в основном методе), и вы делаете:

objOutStr.writeObject(Building2);

Таким образом, объект BuildingGUI сериализуется, как и ожидалось. Если вы хотите сериализовать объект Building, вам нужен доступ к нему, например, с помощью геттера:

public Building getBuilding() {
  return theBuilding;
}

Затем замените в своем коде на: objOutStr.writeObject(Building2.getBuilding());

Тогда, когда произойдет десериализация, у вас будет объект класса Building.

0 голосов
/ 21 января 2019

Поскольку вы утверждаете, что ваш код работает, я просто скопировал его и вставил из исходного вопроса.

Вы были на правильном пути, вы просто:

  1. Нужнометод, который при вызове из вашего основного файла будет принимать BuildingGUI в качестве аргумента и сериализовать его для хранения на диске.
  2. Нужен метод, который при вызове будет принимать имя файла в качестве аргумента, de-сериализуйте файл и верните вам 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();
}
...