2011-01-05 32 views
5

Im chỉ tự hỏi làm thế nào tôi sử dụng XMLEncoder để serialize ArrayList<foo> nơi foo là lớp học của riêng tôi.XMLEncoder trong java cho serialization

Tôi có phải làm bất cứ điều gì cụ thể, tức là xác định cấu trúc xml của riêng mình trước và sau đó gọi toString trên mỗi giá trị trong danh sách của tôi và viết nó ra?

Có ai có thể chỉ cho tôi một hướng dẫn hay không? http://java.sun.com/products/jfc/tsc/articles/persistence4/ Thats những gì tôi đã được nhìn vào nhưng nó doesnt dường như đề cập đến những gì để làm với các lớp học không thư viện.

Cảm ơn

Trả lời

9

Nếu bạn đang tìm kiếm XML serialization tôi sẽ đề nghị bạn để đi cho 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> 
10

Không có gì đặc biệt về serializing một ArrayList với XMLEncoder là.

Dưới đây là một ví dụ:

Có một TestBean lớp bean:

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

Và một lớp chính mà serialize một ArrayList<TestBean> và đọc nó trở lại một lần nữa:

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

Và sau đó đầu ra là:

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]] 

Phương thức toString() trong TestBean chỉ để in đẹp. Nó không ảnh hưởng đến việc tuần tự hóa XML.

+0

Tôi thấy điều này không hoạt động, ví dụ xstream đã hoạt động tốt mặc dù – Sara

+0

Chính xác thì điều gì không hiệu quả với bạn? Tôi trích xuất này từ mã ví dụ làm việc. Bạn đã thực hiện các getters và setters trong TestBean? Tôi chỉ chèn một bình luận thích hợp cho điều đó. – vanje

+0

Triển khai này hoạt động đối với các lớp được mã hóa theo quy ước JavaBeans, nhưng đối với các lớp do người dùng định nghĩa tùy ý, cần đảm bảo rằng XMLEncoder có đúng PersistenceDelegates tại chỗ. Không phải tất cả các lớp đều có các thuộc tính và không phải tất cả các thuộc tính đều có thể ghi được - lớp của bạn càng thêm từ quy ước JavaBeans, bạn càng phải nỗ lực nhiều hơn. – Johansensen

2

XMLEncoder có thể được sử dụng cho bất kỳ lớp nào, bao gồm cả người dùng xác định - bài viết bạn đề cập chi tiết cách thực hiện, nhưng nó không được viết rất tốt để có thể hơi khó hiểu.

Nếu lớp do người dùng xác định của bạn theo sau JavaBeans spec, thì bạn chỉ có thể sử dụng encoder.writeObject() để tuần tự hóa một phiên bản List<Foo>. Điều này là do đầu ra XML chỉ là một loạt các hướng dẫn về cách tạo lại cá thể đã cho lúc chạy. PersistenceDelegate mặc định biết cách serialize cấu trúc List, nhưng chỉ có hành vi mặc định cho các lớp không xác định. Theo mặc định, nó cố gắng tạo lại một cá thể đối tượng cụ thể bằng cách gọi hàm tạo nullary (no-argument) của nó, và sau đó thiết lập các thuộc tính của nó từng cái một với các giá trị của cá thể đã cho - một thứ được bảo đảm là có thể nếu lớp đó là một JavaBean.

Nếu lớp học của bạn có một số thuộc tính chỉ đọc, tức là chúng được thiết lập bởi hàm tạo và không thể thay đổi sau thời gian xây dựng, thì bạn phải làm (hơi) nhiều hơn để làm cho nó hoạt động. Bạn có thể tạo một thể hiện tùy chỉnh của DefaultPersistenceDelegate để nhận biết lớp của bạn và biết cách truyền dữ liệu thích hợp cho hàm khởi tạo của nó - bạn chỉ cần chuyển tên của thuộc tính vào danh sách, và nó sẽ thực hiện phần còn lại:

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

Nếu lớp của bạn có đối số hàm tạo không trực tiếp ánh xạ tới thuộc tính bằng phương thức getter và/hoặc có các phức tạp khác để khôi phục trạng thái đối tượng, bạn có thể làm việc xung quanh bằng cách mở rộng PersistenceDelegate và thực hiện hành vi cần thiết.Tuy nhiên, nếu lớp của bạn rất phức tạp để tái tạo khi chạy và bạn muốn nó được sắp xếp theo thứ tự, bạn nên cân nhắc thiết kế lại nó để giảm độ phức tạp của nó - điều này sẽ làm cho toàn bộ quá trình trở nên dễ dàng hơn, và sẽ giảm thiểu cơ hội lỗi cũng như làm cho nó dễ dàng hơn để thay đổi và mở rộng trong tương lai.

0

Tôi không chắc tại sao rất nhiều ví dụ trên internet không đầy đủ hoặc không hoạt động khi nó chỉ chú ý một chút để chúng trở nên hữu ích hơn nhiều. Đây là một ví dụ hoàn chỉnh có thể được thực hiện trong một tệp (PersonBean.java) và nó hoạt động!

// 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) { 
    } 
    } 
}