我有以下问题:
我有一个XML文件(大约1GB),并且必须上下迭代(即不顺序;一个接一个地),以便获得所需的数据并对其进行一些操作。最初,我使用了DOM Java包,但显然,在解析XML文件时,JVM会达到其最大堆空间并停止。
为了克服这个问题,我提出的解决方案之一是找到另一个迭代XML中每个元素的解析器,然后将它的内容存储在硬盘上的临时SQLite数据库中。因此,通过这种方式,不会超出JVM的堆,并且一旦填满所有数据,我就会忽略XML文件并继续对临时SQLite数据库执行操作。
还有另一种方法可以解决我的问题吗?
SAX(XML的简单API) 会帮助你。
与DOM解析器不同,SAX解析器不会创建内存
XML文档的表示,因此更快,使用更少
记忆。相反,SAX解析器会通知客户端XML文档
结构通过调用回调,即通过调用a上的方法
org.xml.sax.helpers.DefaultHandler
实例提供给解析器。
这是一个示例实现:
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
DefaultHandler handler = new MyHandler();
parser.parse("file.xml", handler);
在哪里 MyHandler
定义生成文档/元素的开始/结束等事件时要采取的操作。
class MyHandler extends DefaultHandler {
@Override
public void startDocument() throws SAXException {
}
@Override
public void endDocument() throws SAXException {
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
}
// To take specific actions for each chunk of character data (such as
// adding the data to a node or buffer, or printing it to a file).
@Override
public void characters(char ch[], int start, int length)
throws SAXException {
}
}
如果你不想受到约束 记忆限制,我当然建议您使用当前的方法,并将所有内容存储在数据库中。
解析XML文件应该由a完成 SAX parser
,每个人都推荐(包括我)。这样,您可以一次创建一个对象,并且可以立即将其持久保存到数据库中。
对于后处理(解析交叉引用),您可以使用 SELECT
来自数据库,制作主键,索引等。如果您对此感到满意,也可以使用ORM(Eclipselink,Hibernate)。
实际上我并不是真的推荐SQLite,它更容易设置MySQL服务器,并将数据存储在那里。稍后您甚至可以重用XML数据(如果不删除)。
如果你想使用比SAX更高级的方法,这可能是非常棘手的编程,你可以使用最新的Saxon-EE版本来查看流式XSLT转换。但是,您对于您正在进行的精确处理过于模糊,以了解这是否适用于您的特定情况。
如果你需要一个资源友好的方法来处理非常大的xml试试这个:
http://www.xml2java.net/xml-to-java-data-binding-for-big-data/
它允许您以SAX方式处理数据,但具有获取高级事件(xml数据映射到java)的优势,并且能够直接在代码中处理这些对象。所以它结合了jaxb便利性和SAX资源友好性。