我有一个使用XmlUnit从两个XML文件中获取差异的应用程序。 但问题是XmlUnit使用JDOM。我的xml文件大约1GB!
将这些xml存储在JDOM文档中需要太多RAM。
我曾尝试使用SlimJDOMFactory,但仍使用太多RAM !!
实际上我需要在XML文件中向前和向后导航。没有JDOM我找不到简单的方法。
有人可以帮忙吗?
以下是我如何构建JDOM文档的代码示例:
private org.jdom2.Document refDocJdom2;
private org.jdom2.Document resDocJdom2;
SAXBuilder sxb = new SAXBuilder();
sxb.setJDOMFactory(new SlimJDOMFactory());
popmsg("Validating reference file...");
try {
refDocJdom2 = sxb.build(referenceXML_Path);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Error while parsing Reference : "+referenceXML_Path+" file.\nCheck XML file validity.");
return;
}
popmsg("Reference file validated");
popmsg("Validating result file....");
try {
resDocJdom2 = sxb.build(resultXML_Path);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Error while parsing result "+resultXML_Path+" file.\nCheck XML file validity.");
return;
}
popmsg("Result file validated");
popmsg("Validation Done.");
getDifferencies(referenceXML_Path, resultXML_Path);
d2 = new Date();
}
public void getDifferencies(String fileRef, String fileRes) throws SAXException, IOException {
popmsg("Documents : VALID XML format");
popmsg("Shearching for differencies....");
Reader refReader;
refReader = new FileReader(fileRef);
Reader resReader = new FileReader(fileRes);
Diff aDifference = new Diff(refReader, resReader);
if(refReader != null){
refReader.close();
}
refReader = null;
if(resReader != null){
resReader.close();
}
resReader = null;
//TODO
// XMLUnit.setIgnoreWhitespace(true);
myDetailledDiff = new DetailedDiff(aDifference);
myDetailledDiff.overrideDifferenceListener(new IgnoreNamedElementsDifferenceListener());
myDetailledDiff.overrideElementQualifier(new ElementNameAndAttributeQualifier());
allDiffs = myDetailledDiff.getAllDifferences();
myDetailledDiff = null;
popmsg("Got all differencies...\nGoing to Sort them now...");
popmsg("Diff SIZE : "+allDiffs.size());
myDiffsList = new ArrayList<MyDifference>(allDiffs.size());
if(allDiffs.size() > 0){
Difference aDiff;
for (int i = 0; i < allDiffs.size(); i++){
aDiff = (Difference) allDiffs.get(i);
myDiffsList.add(new MyDifference(aDiff, refDocJdom2, resDocJdom2));
if(myDiffsList.size() == LIMIT)
return ;
if (i%25 == 0 && i!= 0){
popmsg("**************************************************\t"+i+"\n");
}
}
allDiffs.clear();
allDiffs = null;
}else{
popmsg("NO DIFERENCIES");
}
}
答案 0 :(得分:9)
JDOM将整个XML Document读入内存。对于任何基于内存的XML模型(XOM / DOM / JDOM /等),这都是“正常的”。这也是这些系统众所周知的弱点。最终,没有解决此问题的方法,同时仍保留整个XML的内存中表示。
当读取XML文档(通常是UTF-8)时,磁盘上的1GB数据通常会按比例转换为内存中的许多字符,大约为2GB。这就是你应该为1GB XML文档“预算”的内容。
SlimJDOMFactory在XML中重用了字符串,而不是保留对新的字符串的引用,实质上它是对字符串值进行重复数据删除。当您有许多具有相同名称的元素,标签和其他结构时,这非常方便。例如,如果没有SlimJDOMFactory,具有1M <tag />
元素的XML文档将具有1M个不同的Element实例,每个实例都有自己的名称tag
。假设tag
大约是32Byte对象,那么存储这些字符串需要大约32MB。 SlimJDOMFactory将减少到只有32Bytes,但是,这只是'到目前为止',并没有解决这样一个事实:随着文档的增长,它将需要更多的空间.....它只是'延迟'当你运行内存不足。它有一些其他的后果,包括好的和坏的....:好,它减少了垃圾收集时间,因为用于扫描的内存较少,它会减少(略微)文档加载时间,因为它重复数据删除。我的测试表明,对于存储在内存中甚至几个GC周期的文档,可以快速实现较小内存占用空间的净效益,并且解析端的性能成本可以“回收”。
此问题的典型解决方案是:
这些解决方案都不是“很棒”,但这就是内存中的XML系统所能提供的。