最近帮同事处理一个老项目,程序一启动就要加载几百兆的XML配置文件,等得人都快睡着了。其实这种情况挺常见的,尤其是一些企业级系统或者老旧平台还在大量使用XML做数据交换。别急着换格式,先试试这些实打实能提升解析速度的办法。
选对解析器很关键
很多人用Java处理XML,默认就上DocumentBuilder,结果一碰到大文件直接卡住。这是因为DOM解析会把整个XML树全读进内存,数据一大,机器就开始喘气。这时候换成SAX或者StAX就好很多。
SAX是事件驱动的,边读边处理,内存占用小。比如你要从一个1GB的XML日志里找特定记录,用SAX只关心目标节点,其他内容扫过去就扔,效率高得多。
<?xml version="1.0" encoding="UTF-8"?>
<data>
<item id="1001">...</item>
<item id="1002">...</item>
</data>
用StAX更灵活
StAX算是折中方案,既能像SAX一样流式读取,又支持按需跳转。在Java里用XMLInputFactory创建StreamReader,可以逐个读取元素而不加载全部内容。
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new FileInputStream("large.xml"));
while (reader.hasNext()) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT && "item".equals(reader.getLocalName())) {
// 只处理item节点
}
}
压缩和缓存也管用
如果XML是网络传输来的,先gzip压缩一下,体积能减掉七八成。接收端解压再解析,整体时间反而更短。另外,不变的配置文件别每次都重新解析,第一次处理完存成对象或序列化文件,下次直接加载。
减少不必要的验证
默认情况下,很多解析器会去校验DTD或Schema,尤其是外网来的文档,一查外部资源就特别慢。如果你确定数据来源可靠,关掉验证能省不少时间。
factory.setFeature("http://apache.org/xml/features/validation/schema", false);
factory.setFeature("http://xml.org/sax/features/validation", false);
结构设计也有讲究
有些XML嵌得太深,一层套一层,解析起来自然费劲。能扁平化的尽量扁平,比如把多层嵌套改成属性存储。还有就是避免在文本内容里塞大量特殊字符,转义处理也很耗时。
说到底,XML本身不是瓶颈,怎么用才是关键。工具选对了,结构理顺了,哪怕文件再大,解析也能跑得起来。