SAX 解析大型XML文件
程序员文章站
2022-01-20 10:05:59
...
最近在项目中需要把一些系统配置表导到XML文件中,一开始觉得数据量不大,使用dom4j就可以了,后来才发现数据量超出预期的大小,程序很快就内存溢出了。SAX在顺序遍历XML所有节点时,还是有很大的优势的。下面是我写的SAX解析XML的代码,解析大型XML文件来说性能比较好。
DefaultElementHandler.java
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public abstract class DefaultElementHandler extends DefaultHandler{
//入栈标志
private boolean begin;
//节点名称
private String tagName;
//内容缓冲区
private StringBuilder sb;
//带节点名称的构造方法
public DefaultElementHandler(String tagName) {
this.tagName = tagName;
this.begin = false;
this.sb = new StringBuilder();
}
/**
* 处理节点开始
*/
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (qName.equals(tagName) || begin) {
sb.append("<");
sb.append(qName);
sb.append(" ");
int attrCount = attributes.getLength();
for(int i=0;i<attrCount;i++){
sb.append(attributes.getQName(i));
sb.append("=\"");
sb.append(attributes.getValue(i));
sb.append("\" ");
}
sb.append(">");
begin = true;
}
}
/**
* 处理节点内容
*/
public void characters(char[] ch, int start, int length)
throws SAXException {
String text = new String(ch, start, length);
if (text.trim().equals(""))
return;
if (begin)
sb.append(text);
}
/**
* 处理节点结束
*/
public void endElement(String uri, String localName, String qName)
throws SAXException {
String stag = "</" + tagName + ">";
String ntag = "</" + qName + ">";
if (stag.equals(ntag) || begin) {
sb.append(ntag);
if (stag.equals(ntag)) {
begin = false;
try {
Document doc = DocumentHelper.parseText(sb.toString());
Element element = doc.getRootElement();
this.processElement(element);
} catch (DocumentException e) {
e.printStackTrace();
}
sb.setLength(0);
}
}
}
/**
* 对节点进行操作
* @param element
*/
public abstract void processElement(Element element);
}
SAXReadXML
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.dom4j.Element;
public class SAXReadXML {
/**
* @param args
* @throws Exception
* @throws
*/
public static void main(String[] args) throws Exception {
SAXParserFactory sf = SAXParserFactory.newInstance();
SAXParser sax = sf.newSAXParser();
//"TABLE"是需要处理的节点
sax.parse("d:\\myxml.xml", new DefaultElementHandler("TABLE"){
@Override
public void processElement(Element element) {
//这里获得了每一个"TABLE"节点,在这里做具体的操作。
System.out.println(element.asXML());
}
});
}
}
用这段程序解析1GB的XML文件都不会出现内存溢出,而且同时拥有dom4j对节点处理的方便性。
myxml.xml
<?xml version="1.0" encoding="UTF-8"?> <TABLES> <TABLE> <ID>ID0</ID> <NAME>NAME0</NAME> <VALUE>VALUE0</VALUE> <DESC>DESC0</DESC> <COLUMNS> <COLUMN> <C1>C10</C1> <C2>C20</C2> <C3>C30</C3> </COLUMN> <COLUMN> <C1>C10</C1> <C2>C20</C2> <C3>C30</C3> </COLUMN> </COLUMNS> </TABLE> <TABLE> <ID>ID1</ID> <NAME>NAME1</NAME> <VALUE>VALUE1</VALUE> <DESC>DESC1</DESC> <COLUMNS> <COLUMN> <C1>C11</C1> <C2>C21</C2> <C3>C31</C3> </COLUMN> <COLUMN> <C1>C11</C1> <C2>C21</C2> <C3>C31</C3> </COLUMN> </COLUMNS> </TABLE> <TABLE> <ID>ID2</ID> <NAME>NAME2</NAME> <VALUE>VALUE2</VALUE> <DESC>DESC2</DESC> <COLUMNS> <COLUMN> <C1>C12</C1> <C2>C22</C2> <C3>C32</C3> </COLUMN> <COLUMN> <C1>C12</C1> <C2>C22</C2> <C3>C32</C3> </COLUMN> </COLUMNS> </TABLE> </TABLES>
下一篇: JDOM解析XML简单应用