【问题标题】:serializing a list of objects into a file in java将对象列表序列化为java中的文件
【发布时间】:2012-01-08 15:05:16
【问题描述】:

我有一个大约 20,000 个对象的列表,这些对象又具有非常庞大的层次结构。我需要将对象转储到文件中,以便以后在处理过程中随时读取。现在我的问题是,我在 Java 上工作过,但在序列化方面的工作不多,而且我没有那么多知识如何做到这一点。

据我所知,在这种情况下,我需要同时使用序列化和反序列化。任何人都可以请帮助。我也可以使用任何新的 API 或普通的 Java 序列化。

问候。

【问题讨论】:

  • 为什么需要将对象转储到文件中?你可以改用数据库吗?

标签: java serialization deserialization


【解决方案1】:

我给你一个样本

import java.io.Serializable;

public class Account implements Serializable {

    private int accountNo;
    private String custName;
    private int balance;

    /** Creates a new instance of Account    */
    public Account(int accNo, String name, int bal) {
        this.accountNo = accNo;
        this.custName = name;
        this.balance = bal;
    }

    @Override
    public String toString() {
        String str = "Account No:" + this.accountNo;
        str += "\nCustomer name:" + this.custName;
        str += "\nBalance:" + this.balance;
        return str;
    }
}

读写对象

package me.dev;

import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main {

    public void writeObject(ArrayList<Object> listAccount) throws IOException {
        //Create FileOutputStream to write file
        FileOutputStream fos = new FileOutputStream("C:\\bank.datum");
        //Create ObjectOutputStream to write object
        ObjectOutputStream objOutputStream = new ObjectOutputStream(fos);
        //Write object to file
        for (Object obj : listAccount) {

            objOutputStream.writeObject(obj);
            objOutputStream.reset();
        }
        objOutputStream.close();
    }

    public ArrayList<Account> readObject() throws ClassNotFoundException, IOException {
        ArrayList<Account> listAccount = new ArrayList();
        //Create new FileInputStream object to read file
        FileInputStream fis = new FileInputStream("C:\\bank.datum");
        //Create new ObjectInputStream object to read object from file
        ObjectInputStream obj = new ObjectInputStream(fis);
        try {
            while (fis.available() != -1) {
                //Read object from file
                Account acc = (Account) obj.readObject();
                listAccount.add(acc);
            }
        } catch (EOFException ex) {
            //ex.printStackTrace();
        }
        return listAccount;
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws ClassNotFoundException {
        try {
            // TODO code application logic here
            ArrayList<Object> listAcc = new ArrayList<Object>();
            listAcc.add(new Account(1, "John", 1000));
            listAcc.add(new Account(2, "Smith", 2000));
            listAcc.add(new Account(3, "Tom", 3000));
            Main main = new Main();
            main.writeObject(listAcc);
            ArrayList<Account> listAccount = main.readObject();
            System.out.println("listisze:" + listAccount.size());
            if (listAccount.size() > 0) {
                for (Account account : listAccount) {
                    System.out.println(((Account) account).toString());
                }
            }
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

【讨论】:

  • 将对象读入局部变量然后返回boolean 而不是变量的readObject() 方法用处不大。调用available() 也没什么用,特别是available() == 0 不是EOF 的有效测试。你应该循环调用readObject(),直到EOFException被抛出。
  • 我刚刚写了一个简单的案例。我循环并打印出来。 readObject 是我自己的函数,而不是 java 函数。 @EJP
  • 我再说清楚一点。不返回已读取对象的readObject() 方法完全没有意义。其他反对意见也仍然存在。
  • 好的谢谢 :)) 不过我现在很开心,因为我是学java的时候写的,谢谢评论^^。
【解决方案2】:

看这个链接http://www.java2s.com/Code/Java/File-Input-Output/Objectserialization.htm 它是这样的:

Card3 card = new Card3(12, Card3.SPADES);
    System.out.println("Card to write is: " + card);

    try {
      FileOutputStream out = new FileOutputStream("card.out");
      ObjectOutputStream oos = new ObjectOutputStream(out);
      oos.writeObject(card);
      oos.flush();
    } catch (Exception e) {
      System.out.println("Problem serializing: " + e);
    }

    Card3 acard = null;

    try {
      FileInputStream in = new FileInputStream("card.out");
      ObjectInputStream ois = new ObjectInputStream(in);
      acard = (Card3) (ois.readObject());
    } catch (Exception e) {
      System.out.println("Problem serializing: " + e);
    }

    System.out.println("Card read is: " + acard);

别忘了在你想保存的所有类中实现 Serializable 接口 并将修饰符“瞬态”放在您不想保存的所有字段中。 (例如私有瞬态列表缓存;)

【讨论】:

    【解决方案3】:

    JSON 最近风靡一时,因此您可以使用它。 Jackson 是一个不错的 JSON 序列化/反序列化 api。作为奖励,您可以获得与其他平台的互操作性。

    如果您不害怕 xml,请使用 JAXB

    当然你总是可以使用二进制序列化,但是 IMO 文本比 blob 更容易管理。

    【讨论】:

      【解决方案4】:

      下面是使用 XMLEncoder 将对象写入文件的代码,假设您的对象实现了可序列化接口。

          FileOutputStream os =new FileOutputStream("c:/temp/serialized.xml");
          XMLEncoder encoder=new XMLEncoder(os);
          encoder.writeObject(objectToBeSerialized);
          encoder.close();
      

      下面是反序列化数据的代码

          FileInputStream is=new FileInputStream("c:/temp/serialized.xml");
          XMLDecoder decoder=new XMLDecoder(is);
          Object object=(Object)decoder.readObject(); 
          decoder.close();
      

      【讨论】:

        【解决方案5】:

        您可以直接保存对象列表,而不是单独保存每个对象。我正在使用下面的代码来实现这一点。虽然我是为了克隆而序列化,但学习基础知识应该足够了。

        public static List<EmpoyeeTO> deepCloneList( List<EmpoyeeTO> objectList) {
                try {
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    ObjectOutputStream oos = new ObjectOutputStream(baos);
                    oos.writeObject(objectList);
                    oos.flush();
                    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                    ObjectInputStream ois = new ObjectInputStream(bais);
                    return (List<EmpoyeeTO>) ois.readObject();
                }catch(EOFException eof){
                    return objectList;
                } 
                catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
        

        【讨论】:

        • 这正是我所需要的,尽管对于 UnmodifiableCollection 来说,这段代码很简单。干净、直接且易于理解。我无法理解它是如何没有任何投票的,因为它完全符合问题的标题所代表的含义。
        • 可能是因为它没有序列化为文件,如标题所述。
        猜你喜欢
        • 2023-04-03
        • 1970-01-01
        • 1970-01-01
        • 2011-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-14
        • 1970-01-01
        相关资源
        最近更新 更多