【问题标题】:XMLEncoder in java for serializationjava中用于序列化的XMLEncoder
【发布时间】:2015-10-09 01:17:38
【问题描述】:

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

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

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

谢谢

【问题讨论】:

    标签: java serialization


    【解决方案1】:

    如果您正在寻找 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】:

      使用 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&lt;TestBean&gt; 并再次读回它:

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

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

      【讨论】:

      • 我发现这不起作用,但 xstream 示例效果很好
      • 究竟有什么不适合您?我从工作示例代码中提取了这个。您是否在 TestBean 中实现了 getter 和 setter?我只插入了一个适当的评论。
      • 此实现适用于按照 JavaBeans 约定编码的类,但对于任意用户定义的类,必须确保 XMLEncoder 具有正确的 PersistenceDelegates。不是所有的类都有属性,也不是所有的属性都是可写的——你的类离 JavaBeans 约定越远,你需要付出的努力就越多。
      【解决方案3】:

      XMLEncoder 可以用于任何类,包括用户定义的类——你提到的文章详细说明了如何做到这一点,但它写得不是很好,所以可能有点难以理解。

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

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

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

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

      【讨论】:

        【解决方案4】:

        我不确定为什么互联网上有这么多示例不完整或不起作用,而只需稍加注意,它们就会变得更有用。这是一个可以在一个文件(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) {
            } 
          }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-30
          • 1970-01-01
          • 2014-08-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多