我有以下问题:
我有一个XML文件(大约1GB),并且必须上下迭代(即不顺序;一个接一个地),以便获得所需的数据并对其进行一些操作。最初,我使用了DOM Java包,但很明显,在解析XML文件时,JVM达到了最大堆空间并停止了。
为了克服这个问题,我提出的解决方案之一是找到另一个迭代XML中每个元素的解析器,然后将它的内容存储在硬盘上的临时SQLite数据库中。因此,这样就不会超出JVM的堆,一旦填满所有数据,我就会忽略XML文件并继续对临时SQLite数据库进行操作。
还有另一种方法可以解决我的问题吗?
答案 0 :(得分:12)
与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 {
}
}
答案 1 :(得分:3)
如果您不想受内存限制的约束,我当然建议您使用当前的方法,并将所有内容存储在数据库中。
解析XML文件应该由SAX parser
完成,正如大家所建议的那样(包括我)。这样,您可以一次创建一个对象,并且可以立即将其保存到数据库中。
对于后处理(解析交叉引用),您可以使用数据库中的SELECT
,制作主键,索引等。如果您觉得可以使用ORM(Eclipselink,Hibernate)对此很满意。
实际上我并不真的推荐SQLite,设置MySQL服务器更容易,并将数据存储在那里。稍后您甚至可以重复使用XML数据(如果您不删除)。
答案 2 :(得分:1)
如果你想使用比SAX更高级的方法,这可能非常难以编程,你可以使用最新的Saxon-EE版本来查看流式XSLT转换。但是,您对于您正在进行的精确处理过于模糊,以了解这是否适用于您的特定情况。
答案 3 :(得分:0)
如果您需要一种资源友好的方法来处理非常大的xml,请尝试以下方法: http://www.xml2java.net/xml-to-java-data-binding-for-big-data/ 它允许您以SAX方式处理数据,但具有获取高级事件(xml数据映射到java)的优势,并且能够直接在代码中处理这些对象。所以它结合了jaxb便利性和SAX资源友好性。