java中的XMLEncoder用于序列化

时间:2011-01-05 08:49:50

标签: java serialization

我只是想知道我如何使用XMLEncoder来序列化ArrayList<foo>,其中foo是我自己创建的类。

我是否必须做任何特别的事情,即首先定义我自己的xml结构,然后在列表中的每个值上调用toString并写出来?

有人能指点我一个好的教程吗? http://java.sun.com/products/jfc/tsc/articles/persistence4/这就是我一直在看的东西,但它似乎没有提到如何处理非库类。

由于

4 个答案:

答案 0 :(得分:10)

使用XMLEncoder序列化ArrayList没什么特别的。

以下是一个例子:

有一个bean类TestBean:

public class TestBean {

  private String name;
  private int age;

  public TestBean() {
    this.name = "";
    this.age = 0;
  }

  public TestBean(String name, int age) {
    this.name = name;
    this.age = age;
  }

  // Getter and setter ...

  @Override
  public String toString() {
    return String.format("[TestBean: name='%s', age=%d]", name, age);
  }
}

一个Main类,它序列化ArrayList<TestBean>并再次读回来:

public class Main {
  private static final String FILENAME = "testbeanlist.xml";

  public static void main(String[] args) {
    try {
      // Create a list of TestBean objects ...
      final List<TestBean> list = new ArrayList<TestBean>();
      list.add(new TestBean("Henry", 42));
      list.add(new TestBean("Tom", 11));

      System.out.println("Writing list to file " + FILENAME + ": " + list);

      // ... and serialize it via XMLEncoder to file testbeanlist.xml
      final XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(
          new FileOutputStream(FILENAME)));
      encoder.writeObject(list);
      encoder.close();

      // Use XMLDecoder to read the same XML file in.
      final XMLDecoder decoder = new XMLDecoder(new FileInputStream(FILENAME));
      final List<TestBean> listFromFile = (List<TestBean>) decoder.readObject();
      decoder.close();

      System.out.println("Reading list: " + listFromFile);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
  }
}

然后输出是:

Writing list to file testbeanlist.xml: [[TestBean: name='Henry', age=42], [TestBean: name='Tom', age=11]]
Reading list: [[TestBean: name='Henry', age=42], [TestBean: name='Tom', age=11]]

toString()中的TestBean方法仅适用于漂亮打印。它不会影响XML序列化。

答案 1 :(得分:9)

如果您正在寻找XML序列化,我建议您转到XStream

Person joe = new Person("Joe", "Walnes");
joe.setPhone(new PhoneNumber(123, "1234-456"));
joe.setFax(new PhoneNumber(123, "9999-999"));

String xml = xstream.toXML(joe);

<person>
  <firstname>Joe</firstname>
  <lastname>Walnes</lastname>
  <phone>
    <code>123</code>
    <number>1234-456</number>
  </phone>
  <fax>
    <code>123</code>
    <number>9999-999</number>
  </fax>
</person>

答案 2 :(得分:3)

XMLEncoder可用于任何类,包括用户定义的类 - 您提到的文章详细说明了如何执行此操作,但编写得不是很好,因此可能有点难以理解。

如果您的用户定义的类遵循JavaBeans spec,那么您只需使用encoder.writeObject()来序列化List<Foo>实例。这是因为XML输出只是一系列有关如何在运行时重新创建给定实例的指令。默认的PersistenceDelegate知道如何序列化List结构,但只有未知类的默认行为。默认情况下,它会尝试通过调用其nullary(无参数)构造函数来重新创建给定的对象实例,然后将其属性逐个设置为给定实例的值 - 如果该类是JavaBean,则可以保证这是可能的。 / p>

如果你的类有一些只读的属性,即它们是由构造函数设置的,并且在构造时间之后无法更改,那么你必须(略微)更多才能使它工作。您可以创建一个DefaultPersistenceDelegate的自定义实例来识别您的类,并知道如何将适当的数据传递给它的构造函数 - 您只需将属性的名称作为列表传递给它,它将完成其余的工作:

PersistenceDelegate fooDelegate = new DefaultPersistenceDelegate(new String[] {"propertyName1", "propertyName2"});
encoder.setPersistenceDelegate(Foo.class, fooDelegate);

如果您的类具有不使用getter方法直接映射到属性的构造函数参数,并且/或者还有其他复杂性来恢复对象状态,您通常可以通过扩展PersistenceDelegate并自己实现必要的行为来解决这些问题。但是,如果您的类在运行时重新创建非常复杂并且希望将其序列化,那么您应该认真考虑重新设计它以降低其复杂性 - 这将使整个过程更加容易,并且将极大地减少出错的可能性,如以及将来更容易改变和扩展。

答案 3 :(得分:2)

我不确定为什么互联网上有这么多的例子是不完整的或不起作用的时候只需要一点注意它们就会更有用。这是一个可以在一个文件(PersonBean.java)中实现的完整示例,它可以工作!

// This example creates two PersonBeans, creates an ArrayList, adds the beans to the
// list, serializes the ArrayList to an XML file.
// It then loads from the XML file into a new ArrayList
//
// Keywords: ArrayList, Serialize, XMLEncode, XMLDecode
// Note: Change the XML file while the 10 second Thread.sleep is waiting to see that
// the data is actually loaded from the file.

import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.beans.XMLEncoder;
import java.beans.XMLDecoder;
import java.util.ArrayList;

public class PersonBean {
  private String name;
  private int    age;

  public String getName() {
    return name; 
  }

  public int getAge() {  
    return age;
  }

  public void setName(String name) { 
    this.name = name; 
  }

  public void setAge(int age) { 
    this.age = age; 
  }

  @Override
  public String toString() {
    return String.format("[PersonBean: name='%s', age=%d]", name, age);
  }

  public static void main(String[] args) {
    PersonBean person1 = new PersonBean();

    person1.setName("Joe");
    person1.setAge(30);

    PersonBean person2 = new PersonBean();

    person2.setName("Jane");
    person2.setAge(25);

    ArrayList arrayList1 = new ArrayList();
    arrayList1.add(person1);
    arrayList1.add(person2);

    try {
      System.out.println("List 'arrayList1' = '" + arrayList1 + "'");
      FileOutputStream outputStream = new FileOutputStream("PersonBean.xml");
      XMLEncoder encoder = new XMLEncoder(outputStream);
      encoder.writeObject(arrayList1);
      encoder.close();
      Thread.sleep(10000);
    } catch (Exception ex) {
    } 

    try {
      FileInputStream inputStream = new FileInputStream("PersonBean.xml");
      XMLDecoder decoder = new XMLDecoder(inputStream);
      ArrayList<PersonBean> arrayList2 = (ArrayList<PersonBean>) decoder.readObject();
      decoder.close();
      System.out.println("List 'arrayList2' = '" + arrayList2 + "'");
    } catch (Exception ex) {
    } 
  }
}