将对象列表序列化成Java文件

9
我有一个大约包含20,000个对象的列表,这些对象又都有一个非常庞大的层级结构。我需要将这些对象导出到一个文件中,以便在我的处理过程中随时可以读取它们。现在我的问题是,我在Java上工作过,但对序列化不太熟悉,也不知道如何做。
据我所知,在这种情况下,我需要使用序列化和反序列化。有谁能帮忙一下吗?同时,我可以使用任何新的API或普通的Java序列化。
谢谢。

为什么需要将对象转储到文件中?你能使用数据库吗? - orlandocr
5个回答

11

看这个链接 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接口,并在所有不想保存的字段上加上修饰符"transient"。 (例如:private transient List cache;)


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;
        }
    }

1
这正是我所需要的,尽管是针对一个“UnmodifiableCollection”,但这段代码很直接、干净且易于理解。我不明白为什么它没有得到任何投票,因为它完全符合问题标题的要求。 - Pere
可能是因为它不像标题所述那样序列化到文件中。 - Roc Boronat

1

JSON最近非常流行,所以您可以使用它。Jackson是一个很好的用于JSON序列化/反序列化的API。作为奖励,您还可以与其他平台进行互操作。

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

当然,您始终可以使用二进制序列化,但在我看来,文本比二进制数据更容易管理。


0

我给你一个样例

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);
        }
    }
}

2
一个readObject()方法,将对象读入本地变量,然后返回一个布尔值而不是变量,这并没有什么用。调用available()也没有什么用,特别是available() == 0不是EOF的有效测试。你应该循环调用readObject()直到抛出EOFException - user207421
我刚写了一个简单的案例。我循环并打印它。readObject是我的自定义函数,不是Java自带的。@EJP - hungneox
2
我会再清楚地说一遍。一个不返回被读取对象的readObject()方法是完全没有意义的。其他反对意见也仍然存在。 - user207421
好的,谢谢你:))但是我现在很开心,因为我在学习Java时写了它,感谢你的评论^^。 - hungneox

0
以下是使用XMLEncoder将对象写入文件的代码,假设您的对象实现了Serializable接口。
    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();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接