Java XML SAX 解析注意
什么时候可以把解析值赋给对象
一般从网上看到的sax解析,都是在Handler中的characters方法进行对象数据的赋值。
示例代码如下:
private TransportFile parseXML(String xml) {
SAXParserFactory saxfac = SAXParserFactory.newInstance();
try {
SAXParser saxparser = saxfac.newSAXParser();
InputStream is = new ByteArrayInputStream(xml.getBytes());
MySAXHandler handler = new MySAXHandler();
saxparser.parse(is, handler);
return handler.getData();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private class MySAXHandler extends DefaultHandler{
String currentTagName = "";
TransportFile mData = null ;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
currentTagName = qName ;
if("file".equals(qName)){
mData = new TransportFile();
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
String str = new String(ch,start,length);
if("guid".equals(currentTagName)){
mData.guid = str;
}else if("name".equals(currentTagName)){
mData.name = str;
}else if("type".equals(currentTagName)){
mData.type = str;
}else if("length".equals(currentTagName)){
mData.length = Long.parseLong(str);
}else if("index".equals(currentTagName)){
mData.index = Integer.parseInt(str);
}else if("count".equals(currentTagName)){
mData.count = Integer.parseInt(str);
}else if("data".equals(currentTagName)){
mData.data = Base64.decode(str);
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
currentTagName = "";
}
public TransportFile getData(){
return mData ;
}
}
普通的使用场景中上述代码没有问题,但是当xml中某一标签的内容很长时,就会引发上述代码的bug。
实践发现sax解析每次也就解析1k左右的数据,超出部分其实是要分段多次解析的。
所以问题来了,如果在characters方法中解析,那么其他几段的数据仍然会不断覆盖最终返回对象中的数据,导致数据丢失。
因此,对于赋值给最终传回对象的数据,在characters阶段只能不断拼接,解析必须在endElement时才可以完成。否则当数据内容比较大的时候,网上代码中的bug就会凸显出来。
顺便贴上我的代码:
private class MySAXHandler extends DefaultHandler{
String currentTagName = "";
TransportFile mData = null ;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
currentTagName = qName ;
mStringBuilder = new StringBuilder();
if("file".equals(qName)){
mData = new TransportFile();
}
}
private StringBuilder mStringBuilder;
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
mStringBuilder.append(ch, start, length);
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
String str = mStringBuilder.toString();
if("guid".equals(currentTagName)){
mData.guid = str;
}else if("name".equals(currentTagName)){
mData.name = str;
}else if("type".equals(currentTagName)){
mData.type = str;
}else if("length".equals(currentTagName)){
mData.length = Long.parseLong(str);
}else if("index".equals(currentTagName)){
mData.index = Integer.parseInt(str);
}else if("count".equals(currentTagName)){
mData.count = Integer.parseInt(str);
}else if("data".equals(currentTagName)){
mData.data = Base64.decode(str);
}
currentTagName = "";
}
public TransportFile getData(){
return mData ;
}
}
characters方法参数注意
ch是当前解析到的字符数组,并不是精确的标签内的内容。
下面是解析第一个标签时characters中 ch 、 start、length输出:
===========characters ch: <?xml version='1.0' encoding='utf-8' standalone='yes' ?><file><guid>678c6f92-d617-40af-bb87-a80c3b2be91f</guid><name>0CAQLTZGO.jpg</name><type>image</type><length>71374</length><index>0</index><count>1</count><data>/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoK.....
===========characters start:31
===========characters length:36
真正当前需要的数据是ch数组从start开始的length个字符。
Java XML SAX 解析注意的更多相关文章
- Java用SAX解析XML
要解析的XML文件:myClass.xml <?xml version="1.0" encoding="utf-8"?> <class> ...
- Java XML Dom解析工具
Java XML Dom解析工具 缩进等 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); ...
- JAVA使用SAX解析XML文件
在我的另一篇文章(http://www.cnblogs.com/anivia/p/5849712.html)中,通过一个例子介绍了使用DOM来解析XML文件,那么本篇文章通过相同的XML文件介绍如何使 ...
- java使用sax解析xml
目的:解析xml文件,并存入mysql,并且要解析的字段能一一对应.这里解析的是微博的文件,想要利用里面的article和person_id字段. 思路: 为了能得到person_id和article ...
- Java中Sax解析XML
SAX基于事件的解析,解析器在一次读取XML文件中根据读取的数据产生相应的事件,由应用程序实现相应的事件处理逻辑,即它是一种“推”的解析方式:这种解析方法速度快.占用内存少,但是它需要应用程序自己处理 ...
- 简单的java使用SAX解析xml
1.新建一个SAXTest类,继承import org.xml.sax.helpers.DefaultHandler类 package com.qiao.SrpingSource; import or ...
- XML SAX解析
SAX是一种占用内存少且解析速度快的解析器,它采用的是事件驱动,它不需要解析完整个文档,而是按照内容顺序,看文档某个部分是否符合xml语法,如果符合就触发相应的事件.所谓的事件就是些回调方法( cal ...
- JavaEE XML SAX解析
SAX解析XML @author ixenos SAX解析工具 SAX解析工具- Sun公司提供的.内置在jdk中.org.xml.sax.* 核心的API: SAXParser类: 用于读取和解析 ...
- 浅谈 Java Xml 底层解析方式
XML 使用DTD(document type definition)文档类型来标记数据和定义数据,格式统一且跨平台和语言,已成为业界公认的标准. 目前 XML 描述数据龙头老大的地位渐渐受到 Jso ...
随机推荐
- 剑指offer四十八之不用加减乘除做加法
一.题目 写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. 二.思路 1. 采用位运算的方法,分三步: (1).两个数异或:相当于每一位相加,而不考虑进位 (2).两个数 ...
- 剑指offer二十八之数组中出现次数超过一半的数字
一.题目 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...
- CentOS常用命令、快照、克隆大揭秘
不多说,直接上干货! cat是查看文件内容, cp –cp是连目录及件文件都拷贝 cp是拷贝文件 a.txt里的内容是, abc def ghi cat a.txt |grep –v gh ...
- 《垃圾回收的算法与实现》——GC标记-清除算法
基本算法 标记-清除算法由 ==标记阶段== 和 ==清除阶段== 构成. 标记即将所有活动的对象打上标记. 清除即将那些没有标记的对象进行回收. 标记与清除 遍历GC root引用,递归标记(设置对 ...
- iptables关键学习总结
iptables技术推荐参考这位仁兄的博客:http://www.zsythink.net/archives/category/%E8%BF%90%E7%BB%B4%E7%9B%B8%E5%85%B3 ...
- Web服务端性能提升实践
随着互联网的不断发展,日常生活中越来越多的需求通过网络来实现,从衣食住行到金融教育,从口袋到身份,人们无时无刻不依赖着网络,而且越来越多的人通过网络来完成自己的需求. 作为直接面对来自客户请求的Web ...
- equal&==&hashcode
== 和 equals 的区别 Object类中的equals方法和“==”是一样的,没有区别,而String类,Integer类等等一些类,是重写了equals方法,才使得equals和“==不同” ...
- mac 上安装 redis
1.从http://redis.io 下载redis包,这里选择了redis-3.2.3 2.将下载的 redis-3.2.3.tar.gz 包拷贝到 /usr/local 目录 3.执行 sudo ...
- C/C++中的常量到底存在了什么地方
一般来说,基本类型(整型.字符型等)常量会在编译阶段被编译成立即数,占的是代码段的内存.(代码段是只读的,而且不允程序员获取代码段的地址,所以在c++中,尽量不为const分配数据段的内存,但是一旦取 ...
- 值得收藏的TCP套接口编程文章
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由jackieluo发表于云+社区专栏 TCP客户端-服务器典型事件 下图是TCP客户端与服务器之间交互的一系列典型事件时间表: 首先启 ...