我需要一个xml解析器来解析大约1.8 GB的文件 所以解析器不应该将所有文件加载到内存中。
有什么建议吗?
答案 0 :(得分:19)
除了推荐的SAX解析之外,您还可以使用JDK(包javax.xml.stream)中包含的StAX API(一种SAX演进)。
答案 1 :(得分:10)
使用基于SAX的解析器,在事件流中向您显示文档的内容。
答案 2 :(得分:4)
与SAX相比,StAX API更易于处理。这是short tutorial
答案 3 :(得分:3)
将文件流式传输到SAX解析器并以块的形式将其读入内存。
SAX为您提供了很多控制,并且事件驱动是有意义的。 api有点难以掌握,你必须注意一些事情,比如调用characters()方法时,但基本的想法是你编写一个内容处理程序,在每个开始和结束时调用读取xml元素。因此,您可以跟踪文档中的当前xpath,确定哪些路径具有您感兴趣的数据,并确定哪个路径标记了要保存或切换或以其他方式处理的块的结尾。
答案 4 :(得分:3)
试试VTD-XML。我发现它比SAX更具性能,更重要的是,更容易使用。
答案 5 :(得分:3)
正如其他人所说,使用SAX解析器,因为它是一个流解析器。使用各种事件,您可以根据需要提取信息,然后将其存储在其他地方(数据库,另一个文件,您有什么)。
如果您真的需要一个次要子集,或者只是简单地总结文件,您甚至可以将其存储在内存中。当然取决于用例。
如果您要假脱机到数据库,请确保您需要注意使您的流程可以重新启动或者其他任何操作。 1.8GB可能会发生很多事情,可能会在中间失败。
答案 6 :(得分:1)
答案 7 :(得分:1)
我遇到了类似的问题 - 我必须阅读整个XML文件并在内存中创建数据结构。在这个数据结构(整个事情必须加载)我不得不做各种操作。很多XML元素都包含文本(我必须在输出文件中输出,但对算法并不重要)。
首先,正如这里所建议的那样,我使用SAX来解析文件并构建我的数据结构。我的文件是4GB,我有一台8GB的机器,所以我认为3GB的文件可能只是文本,而java.lang.String可能需要6GB才能使用它的UTF-16。
如果JVM占用的空间超过计算机具有物理RAM的空间,则计算机将进行交换。执行标记+清除垃圾收集将导致以随机顺序方式访问页面,并且还会将对象从一个对象池移动到另一个对象池,这基本上会杀死计算机。
所以我决定将所有字符串写入文件中的磁盘(FS显然可以处理3GB的顺序写入,并且在OS中读取它时将使用可用内存用于文件系统缓存;可能仍然存在随机访问读取但在java中少于GC)。我创建了一个小帮助程序类,如果它对您有所帮助,欢迎您下载:StringsFile javadoc | Download ZIP
StringsFile file = new StringsFile();
StringInFile str = file.newString("abc"); // writes string to file
System.out.println("str is: " + str.toString()); // fetches string from file
答案 8 :(得分:0)
+1 StaX。它比SaX更容易使用,因为你不需要编写回调(你基本上只是循环遍历所有元素直到你完成)并且(AFAIK)对它可以处理的文件的大小没有限制