XStream

使用XStream的初衷

研究和使用XStream的原因是我在项目中的一个预研。在项目中需要应用到对XML文件的管理和配置,因此需要一个能够将对象保存为XML的工具库,在这里有多种方法实现,我也研究并进行了比对,比如与Zeus工具的比对,与Java自身的XML工具库的比对等。在这里,我就描述下我的XStream学习过程和研究结果。

XStream简单介绍

XStream是一个开源项目,一套简单实用的类库,用于序列化对象与XML对象之间的相互转换。将XML文件内容解析为一个对象或将一个对象序列化为XML文件。

XStream可以用于JDK1.3以上的版本使用,我是在JDK1.5下使用它的。

XStream的相关信息可以到http://xstream.codehaus.org/下查看,它有专门的JavaDoc,可以方便的阅读Xstream的函数及方法。

XStream中主要的类为XStream,它用于序列化对象与XML 对象之间的相互转换。简单的使用它就可以解决很多问题。

XStream中主要的方法也是我用的比较多的是fromXML()和toXML()。

fromXML用于从XML中将对象解析出来。

toXML用于将对象序列化为XML文件。

在XStream中我还使用HierarchicalStreamWriter,HierarchicalStreamReader,createObjectInputStream(),createObjectOutputStream(),主要是用于对象的输入输出。

下面我们来研究下XStream的工作方式。

XStream的实例——将一个序列化对象转化为XML对象。

一,创建XStream对象。

XStream xstream=new XStream();

用默认构造器构造了一个名为xstream的XStream的对象。默认构造器所使用XML解析库为Xpp3库,XPP3是一种运行效率非常高的XML全解析实现。

二,创建需要序列化的对象。

比如这个类就叫PrintUnit。

构造也比较简单,一个简单的JavaBean

public class PrintUnit

{

Private String a;

Private String b;

Private String c;

Public PrintUnit(){}

Public setA(String a)

{

this.a=a;

}

Public getA()

{

return a;

}

Public setB(String b)

{

this.b=b;

}

Public getB()

{

return b;

}

Public setC(String c)

{

This.c=c;

}

Public getC()

{

Return c;

}

}

在例子中使用这个JavaBean。

创建并初始化PrintUnit。

PrintUnit pu=new PrintUnit();

pu.setA("A11");

pu.setB("B22");

pu.setC("C33");

三,创建Writer。

创建一个输出流,至于怎么输出我发现可以使用多种方法,其实原理是一样的。

在这里就不得不提到HierarchicalStreamWriter,HierarchicalStreamWriter是一个接口,从字面上意思来说它是有等级的输入流。同样在XStream中也有不少这个接口的实现类用于输出。我现在所用过的有CompactWriter和PrettyPrintWriter这2个。

我是这样做的:

String str="stream.xml"; //本目录下的一个名为stream的XML文件

PrintWriter pw=new PrintWriter(str);//创建一个PrintWriter对象,用于输出。

之后选用一个HierarchicalStreamWriter的实现类来创建输出。

选用CompactWriter创建:

CompactWriter cw=new CompactWriter(pw);

选用PrettyPrintWriter创建:

PrettyPrintWriter ppw=new PrettyPrintWriter(pw);

两者所使用的方法都是很简单的。

CompactWriter与PrettyPrintWriter的区别在于,以CompactWriter方法输出的为连续的没有分隔的XML文件,而用PrettyPrintWriter方法输出的为有分隔有一定格式的XML文件。

以CompactWriter方式生成的XML文件:

<object-stream><PrintUnit><a>A11</a><b>B22</b><c>C33</c></PrintUnit></object-stream>

以PrettyPrintWriter方式生成的XML文件:

<object-stream>

<PrintUnit>

<a>A11</a>

<b>B22</b>

<c>C33</c>

</PrintUnit>

</object-stream>

我想大家能很容易的分辨出它们的差异。

四,输出操作

以上步骤完成后就可以做输出操作了,XStream的输出方式有多种:toXML方式,ObjectOutputStream方式,marshal方式以及一些我尚未发现的一些其它方式。

先说下我所使用的方式它们各自的不同点,从工作原理上说它们是相似的,但是做法各不相同。

toXML()方法,本身toXML的方法就有2种:

第一种:java.lang.String toXML(java.lang.Object obj)

将对象序列化为XML格式并保存到一个String对象中。

第二种:void toXML(java.lang.Object obj, java.io.Writer out)

将对象序列化为XML格式后以Writer输出到某个地方存储。

我所使用的是第二种方式,使用前面已经做好的Pw就可以实现输出,它其实很简单不需要再去做其它定义,只需要一个PrintWriter对象和需要序列化的Object即可。

直接调用xstream.toXML(printUnit,pw);就能输出XML文件,在这里是输出到该目录下的stream.xml中。这里的输出都是覆盖性的,不是末尾添加形式。

使用ObjectOutputStream方式,简单说它就是生成一个对象输出流。

ObjectOutputStream obj_out = xstream.createObjectOutputStream(ppw);

使用XStream的createObjectOutputStream方法创建一个ObjectOutputStream对象,用于XML的输出。这里使用的是PrettyPrintWriter的方式。   之后调用writerObject方法既可,使用方法与其它输出流类似。

obj_out.writeObject(pu);

obj_out.close();

使用marshal方式,其实marshal方法和toXML方法是相同的。在调用toXML方法进行输出时,在XStream内部是需要调用marshal方法的,然后它再去调用对象marshallingStrategy的marshal方法。所以做toXML其实和marshal是相同的,在这里只是想更加说明它的工作方式。

使用 void marshal(java.lang.Object obj, HierarchicalStreamWriter writer)方法。

延续上面的例子,在这里可以这样写:xstream.marshal(pu,ppw);

需要注意的是,和toXML不同的是参数,一个是PrintWriter对象一个则是PrettyPrintWriter对象。因为marshal中需要

HierarchicalStreamWriter,而PrettyPrintWriter则是实现了HierarchicalStreamWriter接口的实现类。

结果和toXML是相同的。

五,结果:

<object-stream>

<PrintUnit>

<a>A11</a>

<b>B22</b>

<c>C33</c>

</PrintUnit>

</object-stream>

经过以上5步的操作既可将一个序列化对象转化为XML对象。

toXML内部调用图:

 

toXML操作时的内部调用图,自己随意画的。有些没有详细说明。

XStream的实例——将XML文件转化为一个对象

通过上面的一个例子不难看出XStream简便性,既然有了输出就一定会有输入。

输入方我们将会使用ObjectInputStream。

与输出相同我们需要有一个XStream对象,暂且名为xstream。之后需要读取的XML文件地址目录信息。沿用上面的例子。

String inputStr="xstream.xml";

XStream xstream=new XStream();

我们需要通过对象流进行输入操作,所以需要FileReader和BufferedReader。

FileReader fr=new FileReader(inputStr);

BufferedReader br=new BufferedReader(fr);

创建对象输入流

ObjectInputStream obj_input=xstream.createObjectInputStream(br);

创建对象,还是使用PrintUnit这个对象。

PrintUnit pu2;

通过ObjectInputStream中的readObject()方法将对象从XML文件中读取出来。

pu2=(PrintUnit)obj_input.readObject();

获取值:

System.out.println(pu2.getB());

控制台:

B22

从整个输入的过程来看,是一个文件的读取,将其中的对象数据取出来,然后再对这个对象数据进行操作。内容也比较简单通过ObjectInputStream输入对象。

通过以上的输入输出例子,我想大家应该很容易就能理解XStream是如何实现的。

FomXML

上面使用的是以ObjectInputStream的方式进行XML与对象之间进行转换的。下面我将使用XStream中的fromXML()方法进行转换。

首先在使用fromXML我发现一个问题,它必须使用正确的解析方式或输出方式对应的输入方式才可以正常解析读取文件,这个问题有点怪,不过确实存在,当我使用前面ObjectOutputStream方式输出的XML文件,用fromXML()解析读取时,它会报错。

错误信息:

Exception in thread "main" com.thoughtworks.xstream.alias.CannotResolveClassException: object$stream : object$stream

信息内容为:不能解析这个文件。我认为它和输出方式有关,因为上面例子中使用的是ObjectOutputStream,当我反过来做了一个实验后也证明了这一点。

实验大致内容:使用toXML()方法输出XML文件,使用ObjectInputStream解析,发现会在读取的时候抛出CannotResolveClassException异常。

错误信息:

Exception in thread "main" com.thoughtworks.xstream.alias.CannotResolveClassException:

a : a

因此我认为在解析文件的时候必须先要确定这个文件是由什么方式生成的,然后在解析它,对于使用Dom,Dom4j,XPP等不同方式解析尚未尝试。以上测试是在默认的基础上实验的,默认为XPP3的解析器。

使用fromXML的方法。

public java.lang.Object fromXML(java.lang.String xml)

public java.lang.Object fromXML(java.io.Reader xml)

public java.lang.Object fromXML(java.lang.String xml,java.lang.Object root)

public java.lang.Object fromXML(java.io.Reader xml,java.lang.Object root)

例子:

PrintUnit puTwo=(PrintUnit)xstream.fromXML(xml);

这里的xml必须是使用toXML()生成出来的。对于Reader没有太多的要求。

XStream与Java.Bean中XML工具的比较

XStream主要作用是将序列化的对象转化为一个XML文件或将XML文件解析为一个对象。当然并非只有它可以做到,很多其它工具一样可以,在Java中存在这样两个类XMLDecoder和XMLEncoder,它们是在Java.Bean包下的,它们的作用是将JavaBean转化为XML或将XML文件转化为一个Java Bean。

XMLDecoder是通过一个输入流将对象从输入流中取出并转化为一个实例的方法。它所需要的就是一个输入流及一个转化过程。

XMLDecoder的实例:

String fileStr=”xstream.xml”;//XML文件,在本目录下,延用上次使用文件。

ObjectInputStream in=new ObjectInputStream(new FileInputStream(fileStr));//创建一个ObjectInputStream用于输入。

XMLDecoder xmld=new XMLDecoder(in);//创建一个XMLDecoder对象。

延用前面所使用PrintUnit这个Bean。

PrintUnit pu=(PrintUnit)xmld.readObject();//通过XMLDecoder中的readObject方法获得PrintUnit对象。

如果获取到了这个对象那么pu中将有它的值a=A11,b=B22,c=C33。整个过程最好放try

…catch中去,能够捕获一些如:文件不存在等异常。

从操作方式上看XMLDecoder似乎不比XStream差多少,同样是可以通过ObjectInputStream获取XML文件中的对象。它们的差异就是解析的方式不同,XMLDecoder是使用Java自带的XML解析方式,而XStream则是可以自定义的,它可以使用多中方式进行解析。这些是我个人所发现的一些不同点。

XMLEncoder是通过一个输出流将对象序列化并输出为XML文件。它所需要的是一个输出流及一个输出方式。

XMLEncoder的实例:

String fileStr=”xstream.xml”;//定义一个输入的目标文件。

ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(fileStr));//创建一个对象输出流。

XMLEncoder xmle=new XMLEncoder(out);//创建一个XMLEncoder对象。

延用前面所使用PrintUnit这个Bean。

//创建并初始化PrintUnit对象。

PrintUnit pu=new PrintUnit();

pu.setA(“AAA”);

pu.setB(“BBB”);

pu.setC(“CCC”);

xmle.writeObject(pu);//使用XMLEncode的writeObject方法输出pu

xmle.flush();//刷新

xmle.close();//关闭输出流

从上面的代码不难看出,使用XMLEncode方式将对象序列化并输出也是很方便的,简单调用writeObject方法能将普通Bean输出为XML文件。

XML文件的内容:

�_ <?xml version="1.0" encoding="UTF-8"?>

<java version="1.5.0" class="java.beans.XMLDecoder">

<object class="test.PrintUnit">

<void property="a">

<string>AAA</string>

</void>

<void property="b">

<string>BBB</string>

</void>

<void property="c">

<string>CCC</string>

</void>

</object>

w   </java>

XStream分析(2)相关推荐

  1. XStream 反序列化漏洞 (CVE-2020-26258 26259) 的复现与分析

     聚焦源代码安全,网罗国内外最新资讯! Xstream 是 Java 类库,用来将对象序列化成 XML (JSON) 或反序列化为对象.XStream 是一款开源软件,允许在 BSD 许可证的许可下分 ...

  2. 【组件攻击链】XStream组件高危漏洞分析与利用

    组件介绍 XStream是Java类库,用来将对象序列化成XML(JSON)或反序列化为对象.XStream在运行时使用Java反射机制对要进行序列化的对象树的结构进行探索,并不需要对对象作出修改.X ...

  3. XStream反序列化漏洞分析

    XStream反序列化漏洞分析 XStream反序列化漏洞分析 代理模式 EventHandler XStream 生成payload XStream流程分析 写在最后 XStream反序列化漏洞分析 ...

  4. XML,Object,Json分析转换Xstream采用

    XML,Object,Json转换之浅析Xstream的使用 请尊重他人的劳动成果,转载请注明出处:XML,Object,Json转换之浅析Xstream的使用 XStream的是一个简单的库.主要用 ...

  5. [转载] XStream的分析

    参考链接: XStream教程 XStream是一个序列化对象为XML或XML转换为对象的库. 特点: 简化的API; 无映射文件; 高性能,低内存占用; 整洁的XML; 不需要修改对象;支持内部私有 ...

  6. XStream的分析

    XStream是一个序列化对象为XML或XML转换为对象的库.   特点:   简化的API;  无映射文件;  高性能,低内存占用;  整洁的XML;  不需要修改对象;支持内部私有字段,不需要se ...

  7. SpringMVC4.x源码分析(七):使用XStream处理xml请求和响应消息实战

    2019独角兽企业重金招聘Python工程师标准>>> 本节使用MarshallingHttpMessageConverter+xstream来处理xml请求和响应消息,首先加入sp ...

  8. 微信公众平台开发中-SAE不支持XStream框架的解决方案

    问题描述 最近几天(2014年8月20日之后),突然有不少网友反应,柳峰博客中的微信公众平台开发代码在SAE上运行会报错,或者是能正常部署,但向公众号发消息没反应.以前也有一些初学者质疑过我博客中的代 ...

  9. SpringMVC关于json、xml自动转换的原理研究[附带源码分析 --转

    SpringMVC关于json.xml自动转换的原理研究[附带源码分析] 原文地址:http://www.cnblogs.com/fangjian0423/p/springMVC-xml-json-c ...

最新文章

  1. 使用Netty实现的一个简单HTTP服务器
  2. 商城html源码_延边小程序商城
  3. Effective C++ 读后感
  4. WordPress 主题教程 #5c:日志元数据
  5. L1-018 大笨钟 (10 分)
  6. 2011 ACM 0和1思想
  7. mysql中 REPLACE INTO 和 INSERT INTO 的区别
  8. mysql判断范围0到10 11到20_SQL 如何查询日期在一定范围内的数据
  9. linux tomcat 进程杀掉_Linux下启动停止查看杀死Tomcat进程
  10. logstash采集中文乱码
  11. 【实战】替代Flash的,基于JQuery、HTML5文件上传插件
  12. [通讯方式] 串口通信
  13. IBM微码刷新(二)在服务器上使用BoMC介质刷新微码-cuixf@DC
  14. Factors and Factorials
  15. 2019年上半年网络工程师上午真题及答案解析
  16. 导体接地时的静电平衡问题
  17. 迎接2016,一个程序员的总结
  18. 第四章 文件的基本管理和XFS文件系统备份恢复 随堂笔记
  19. Magic Leap 2正式发布:3299美元起,9月底出货
  20. 计算机网络基础自我评价,计算机网络自我评价

热门文章

  1. 深入浅出matplotlib(10):构造圆弧示意图
  2. 微立体个人年终总结计划PPT模板
  3. null和空字符串('')的区别
  4. 思寒漫谈测试人职业发展
  5. Ubuntu16.04+CUDA8.0+cudnn5.1+TensorFlow-GPU详细安装步骤
  6. 法律工作者在用的小众但功能强悍的效率工具有这些
  7. PLC实现十字路口交通灯的控制课程设计毕业设计
  8. iOS 两套自动打包脚本
  9. 陀螺仪偏航角的夹角计算方法
  10. svchost.exe占用内存过高