由于DOM解析需要先读取整个文件到内存再处理,所以如果文件较大的时候非常耗资源。
SAX解析解决了这个问题。
SAX解析器不像DOM那样建立一个完整的文档树,而是在读取文档时激活一系列事件,这些事件被推给事件处理器,然后由事件处理器提供对文档内容的访问。
SAX模型最大的优点是内存消耗小,因为整个文档无需一次加载到内存中,这使SAX解析器可以解析大于系统内存的文档。
实现示例:
首先,同样一个Student类
package com.hb.xml;
/**
* Student节点
*
* @author HuangBin
* @2014年10月7日
*/
public class Student {
String name;
String sex;
int no;
int num;
public String toString() {
return name + " " + sex + " " + no + " " + num;
}
}
1、 创建一个解析器工厂对象
SAXParserFactory factory = SAXParserFactory.newInstance();
2、创建sax解析器
SAXParser sax = factory.newSAXParser();
3、创建DefaultHander对象
MyHander hander = new MyHander();// MyHander extends DefaultHander
4、进行解析
sax.parse(new FileInputStream(new File("student.xml")), hander);
MyHander定义如下:
class MyHander extends DefaultHandler {
String strValue;
public void startDocument() throws SAXException {
// System.out.println("开始解析");
}
public void endDocument() throws SAXException {
// System.out.println("结束解析");
// 在结束解析的时候遍历打印 检查是否正确
for (Student stu : list) {
System.out.println(stu);
}
}
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
// System.out.println("解析到一个元素:" + qName);
if (qName.equals("stu")) {
stu = new Student();
list.add(stu);
String no = atts.getValue("no");
if (no != null) {
stu.no = Integer.parseInt(no);
}
String num = atts.getValue("num");
if (num != null) {
stu.num = Integer.parseInt(num);
}
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
// System.out.println("元素结尾:" + qName);
if (qName.equals("name")) {
stu.name = strValue;
} else if (qName.equals("sex")) {
stu.sex = strValue;
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
strValue = new String(ch, start, length);
// System.out.println(new String(ch, start, length));
}
}
在MyHander中,可以发现,DefaultHander其实就像一个鼠标监听器,也是一种事件处理器,在事件处理器中对其进行解析处理。这里用到了几个基本的。最后一个characters是得到了节点的文本内容。
完整代码:
package com.hb.xml;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* Sax解析
*
* @author HuangBin
* @2014年10月8日
*/
public class SaxTest {
public static ArrayList<Student> list = new ArrayList<Student>();
Student stu;
public static void main(String[] args) throws Exception {
new SaxTest().parse();
}
public void parse() throws Exception {
long long1 = System.currentTimeMillis();
// 创建一个解析器工厂对象
SAXParserFactory factory = SAXParserFactory.newInstance();
// 创建sax解析器
SAXParser sax = factory.newSAXParser();
MyHander hander = new MyHander();
sax.parse(new FileInputStream(new File("student.xml")), hander);
long long2 = System.currentTimeMillis();
System.out.println(long2 - long1);
// 经过对4048k的同一个文件测试,比DOM快4倍多。183/702ms
}
class MyHander extends DefaultHandler {
String strValue;
public void startDocument() throws SAXException {
// System.out.println("开始解析");
}
public void endDocument() throws SAXException {
// System.out.println("结束解析");
// 在结束解析的时候遍历打印 检查是否正确
// for (Student stu : list) {
// System.out.println(stu);
// }
}
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
// System.out.println("解析到一个元素:" + qName);
if (qName.equals("stu")) {
stu = new Student();
list.add(stu);
String no = atts.getValue("no");
if (no != null) {
stu.no = Integer.parseInt(no);
}
String num = atts.getValue("num");
if (num != null) {
stu.num = Integer.parseInt(num);
}
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
// System.out.println("元素结尾:" + qName);
if (qName.equals("name")) {
stu.name = strValue;
} else if (qName.equals("sex")) {
stu.sex = strValue;
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
strValue = new String(ch, start, length);
// System.out.println(new String(ch, start, length));
}
}
}