假设我想在 XML 中存储很多小的配置对象,并且我不太关心格式。JDK 中内置的XMLDecoder类可以工作,据我所知,XStream以类似的方式工作。
每个图书馆的优势是什么?
假设我想在 XML 中存储很多小的配置对象,并且我不太关心格式。JDK 中内置的XMLDecoder类可以工作,据我所知,XStream以类似的方式工作。
每个图书馆的优势是什么?
我真的很喜欢XStream 库。由于提供的 Java 对象,它在输出相当简单的 xml 方面做得非常好。它也适用于从 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 序列化提供的。我上次使用它时,该文件看起来相当讨厌。如果真的不在乎文件的外观,它可以为您工作,并且您可以避免第 3 方依赖,这也很好。我希望使序列化更漂亮的可能性对于 XMLEncoder 也将是一个更大的挑战。
如果您不给名称起别名,XStream 会输出完整的类名。如果上面的 Person 类有
package example;
xml 将具有“example.Person”,而不仅仅是“person”。
另一个建议:考虑使用 JAXB ( http://jaxb.dev.java.net )。如果您使用的是 JDK 1.6,它是捆绑的,请查看“javax.xml.bind”了解详细信息,因此无需额外的外部 jar。
JAXB 相当快。我也喜欢 XStream,但它有点慢。此外,XMLEncoder 有点像玩具(与其他选项相比)......但如果它有效,那么使用它并没有什么坏处。
另外:JAXB 的一个好处是您还可以使用它绑定部分文档(子树);无需为整个文件创建对象。为此,您需要使用 Stax (XMLStreamReader) 指向子树的根元素,然后绑定。无需使用 SAX,即使对于大多数大文件,只要可以逐块处理即可。
如果您计划将所有这些配置对象存储在一个文件中,并且该文件将非常大,那么您上面概述的两个选项都可能会占用大量内存,因为它们都需要将整个文件读入内存以被反序列化。
如果内存使用是一个问题(包含 XML 的文件会非常大),我推荐SAX。
如果内存使用不是问题(包含 XML 的文件不会很大),我会使用默认 JRE(在本例中为 XMLDecoder)中包含的任何内容来删除第 3 方依赖项。
我总是觉得 XStream 很诱人,因为它很容易上手。但是,我总是最终更换它。它真的很麻烦,它的收集处理可能需要做很多工作。
因此,我通常会切换到 JAXB。它比 XStream 健壮得多,几乎没有错误,而且更灵活。
除了@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>
Java 还有一个新的实用程序类,旨在存储配置中典型的键值对集。它是老式的,但非常简单和方便。这是通过java.util.Properties类完成的,这是一个带有序列化选项的 Map 对象。除非您存储整个对象,否则这可能就是您所需要的。
如果您要持久化大量对象或者您的系统需要多线程,您应该避免像瘟疫那样使用 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