【问题标题】:What are the relative advantages of XMLEncoder and XStream?XMLEncoder 和 XStream 的相对优势是什么?
【发布时间】:2008-09-18 19:30:26
【问题描述】:

假设我想在 XML 中存储很多小的配置对象,我不太关心格式。 JDK 中内置的 XMLDecoder 类可以工作,据我所知,XStream 的工作方式类似。

每个库的优势是什么?

【问题讨论】:

    标签: java xml serialization xstream


    【解决方案1】:

    我真的很喜欢XStream 图书馆。它在输出相当简单的 xml 方面做得非常好 作为提供的 Java 对象的结果。它非常适合复制 从 xml 返回的对象也是如此。而且,我们的第 3 方库之一 反正已经依赖了。

    • 我们选择使用它是因为我们想要 我们的 xml 是人类可读的。使用 别名功能很重要 更好。

    • 您可以扩展库,如果您 想要一个对象的某些部分 以更好的方式反序列化。我们 在一种情况下这样做了,所以文件 会有一组度数, 纬度的分和秒 和经度,而不是两个 双打。

    两分钟的教程总结了基本用法,但在 有兴趣将信息保存在一个地方,我会尝试总结一下 在这里,稍微短一点。

    // define your classes
    public class Person {
      private String firstname;
      private PhoneNumber phone;
      // ... constructors and methods
    }
    
    public class PhoneNumber {
      private int code;
      private String number;
      // ... constructors and methods
    }
    

    然后使用库写出xml。

    // initial the libray
    XStream xstream = new XStream();
    xstream.alias("person", Person.class); // elementName, Class
    xstream.alias("phone", PhoneNumber.class); 
    
    // make your objects
    Person joe = new Person("Joe");
    joe.setPhone(new PhoneNumber(123, "1234-456"));
    
    // convert xml
    String xml = xstream.toXML(joe);
    

    您的输出将如下所示:

    <person>
      <firstname>Joe</firstname>
      <phone>
        <code>123</code>
        <number>1234-456</number>
      </phone>
    </person>
    

    返回:

    Person newJoe = (Person)xstream.fromXML(xml);

    XMLEncoder 是为 Java bean 序列化提供的。上次用的时候, 该文件看起来相当讨厌。如果真的不在乎文件的样子,它可以 为您工作,您可以避免第三方依赖,这也很好。我希望使用 XMLEncoder 使序列化更漂亮的可能性也会更大。

    如果您不给名称起别名,XStream 会输出完整的类名。如果上面的 Person 类有

    package example;
    xml 将包含“example.Person”,而不仅仅是“person”。

    【讨论】:

    • XMLEncoder 输出的“讨厌”方面主要是完全限定的类名。如果我选择不设置别名,XStream 对包名有什么作用?我有很多类型;特定于类的代码必须最小化。我将如何编写通用 XSLT 来将任何 XStreamed 类型转换为 JSON?
    • 我不确定您将如何编写 XSLT 以从 XStream 输出转为 JSON?你可以问一个关于 SO 的新问题。 :)
    • 这是好的部分。 JSONalready outputs to JSON。这就是你想要的吗?
    【解决方案2】:

    另一个建议:考虑使用 JAXB (http://jaxb.dev.java.net)。如果您使用的是 JDK 1.6,它是捆绑的,请查看“javax.xml.bind”了解详细信息,因此无需额外的外部 jar。

    JAXB 相当快。我也喜欢 XStream,但它有点慢。此外,XMLEncoder 有点像玩具(与其他选项相比)......但如果它有效,那么使用它并没有什么坏处。

    另外:JAXB 的一个好处是您还可以使用它绑定部分文档(子树);无需为整个文件创建对象。为此,您需要使用 Stax (XMLStreamReader) 指向子树的根元素,然后绑定。无需使用 SAX,即使对于大多数大文件,只要可以逐块处理即可。

    【讨论】:

    • 感谢您的建议。我在区分绑定和序列化,这个问题是针对序列化的。但是,您提到 XMLEncoder 与其他人相比只是一个玩具。能否请您列举 XMLEncoder 中缺少的 XStream 的一些特定功能?
    • 很公平。只是在大多数情况下,基于数据绑定的序列化工作得很好。而且我没有看到任何表明 JAXB 不起作用的东西。 Wrt toy:缺少可配置性,只写 bean(没有基于字段),xml 集成(XE 使用字符串 concat,而不是 xml writer),性能。
    【解决方案3】:

    如果您计划将所有这些配置对象存储在一个文件中,并且该文件将非常大,那么您上面概述的两个选项都可能会占用大量内存,因为它们都需要读取整个文件进入内存进行反序列化。

    如果内存使用是一个问题(包含 XML 的文件会非常大),我推荐SAX

    如果内存使用不是问题(包含 XML 的文件不会很大),我会使用默认 JRE 中包含的任何内容(在本例中为 XMLDecoder)来删除第 3 方依赖项。

    【讨论】:

    • 关键在于,准确地说,是将对象加载到内存中。这是一种反序列化机制。我想要避免的是构建一个 DOM,然后遍历它以生成一个并行对象图,因为那样我会在内存中拥有 两个 副本,这是不必要的。 XMLDecoder 至少是基于 SAX 的。
    【解决方案4】:

    我也更喜欢XStream,因为它非常易于使用和扩展。如果您使用默认设置,您可以快速开始。如果您需要自定义行为,它具有非常干净的 API 和大量扩展点,因此您可以非常精细地控制要调整的内容,而不会干扰编组过程的其他部分。

    由于 XStream 创建的 XML 看起来不错,手动编辑也很简单。如果输出不能满足您的需求,并且可用Converters 的长列表不包含您需要的,那么编写您自己的相当简单。

    一大优点是他们的homepage 上的良好文档。

    【讨论】:

      【解决方案5】:

      我总是觉得 XStream 很诱人,因为它很容易上手。但是,我总是最终更换它。它确实有很多 bug,它的集合处理可能需要大量工作。

      因此,我通常会切换到 JAXB。它比 XStream 更健壮,几乎没有错误,而且更灵活。

      【讨论】:

        【解决方案6】:

        添加到@jay 的答案示例:

        代码:

        PortfolioAlternateIdentifier identifier = new PortfolioAlternateIdentifier();
        identifier.setEffectiveDate(new Date());
        identifier.setSchemeCode("AAA");
        identifier.setIdentifier("123456");
        

        使用 XStream 的输出:

        <PortfolioAlternateIdentifier>
         <effectiveDate>2014-05-02 20:14:15.961 IST</effectiveDate>
         <schemeCode>AAA</schemeCode>
         <identifier>123456</identifier>
        </PortfolioAlternateIdentifier>   
        

        使用 XMLEncoder 的输出:

        <?xml version="1.0" encoding="UTF-8"?> 
         <java version="1.6.0_38" class="java.beans.XMLDecoder"> 
           <object class="PortfolioAlternateIdentifier"> 
            <void property="effectiveDate"> 
          <object class="java.util.Date"> 
           <long>1399041855961</long> 
          </object> 
            </void> 
         <void property="identifier"> 
          <string>123456</string> 
         </void> 
           <void property="schemeCode"> 
            <string>AAA</string> 
           </void> 
          </object> 
        </java> 
        

        【讨论】:

          【解决方案7】:

          Java 还有一个新的实用程序类,旨在存储配置中典型的键值对集。它是老式的,但非常简单和方便。这是通过 java.util.Properties 类完成的,这是一个带有序列化选项的 Map 对象。除非您存储整个对象,否则这可能就是您所需要的。

          【讨论】:

            【解决方案8】:

            如果你要持久化大量对象或者你的系统需要多线程,你应该避免像瘟疫那样使用 XMLEncoder/XMLDecoder。有关可怕的详细信息,请参阅http://matthew.mceachen.us/blog/do-not-want-xmlencoder-129.html

            如果您必须使用 XML,XStream 非常棒。但是问问自己是否真的需要使用 XML。这是一个序列化基准项目,它可能会帮助您找到更好的解决方案:

            http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking

            【讨论】:

              猜你喜欢
              • 2019-02-01
              • 2011-06-17
              • 2011-01-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-12-20
              • 1970-01-01
              相关资源
              最近更新 更多