在java中读取和更新大型xml文件

时间:2013-08-10 19:08:44

标签: java out-of-memory

我有一个大约400 MB的XML文件 我需要找到一个特定元素,然后将其日期属性从mm-dd-yyyy重新格式化为dd-mm-yyyy 这是我正在使用的代码

    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(inputXML);
doc.getDocumentElement().normalize();
//format the date 
    NodeList nodes = doc.getElementsByTagName("empDetails");
    for (int i = 0; i < nodes.getLength(); i++){
    String oldDate =nodes.item(i).getAttributes().getNamedItem("doj").getNodeValue();
    String newValue = //formatted to dd-mm-yyyy 
nodes.item(i).getAttributes().getNamedItem("doj").setTextContent(newValue);
}

    //now write back to file 
    // write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer;        
transformer = transformerFactory.newTransformer();      
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(fileName));     
transformer.transform(source, result);      

但是这会丢失内存 在Windows 32位 - 它失败

所以我在unix盒子上尝试了这个并将内存设置为: java -Xmx3072m -classpath。 MyTest

它确实运行了一段时间但又失败了

问题 - 是否可以处理400 MB的文件,我想选择性更新并保存? (我肯定答案是肯定的) 我的代码是坏的 - 我应该改变什么? (没有unix shell脚本作为替代解决方案请 - 我的意图是使用java) 我应该进一步提高堆大小吗? 谢谢, 萨蒂什南比亚

1 个答案:

答案 0 :(得分:2)

使用StAX api读取文档(如流)同时写出(再次使用StAX)您不想立即更改为临时文件的部分可能会更好。当您到达您感兴趣的部分时,请在将其反馈给临时文件之前更改这些值。完成后,您可以将临时文件重命名为旧文件。

我推荐XMLEventReaderXMLEventWriterXMLEvents你不关心你可以直接从读者传递到作家。这只会将您正在处理的文档的一小部分保留在内存中。

XMLEventReader reader = ...;
XMLEventWriter writer = ...;
XMLEvent cursor;

while(reader.hasNext()){
  cursor = reader.nextEvent();
  if(doICareAboutThisEvent(cursor)){
      writer.add(changeEvent(cursor));
  }else{
      writer.add(cursor);
  }

}

显然,实现可能会更复杂,您决定关注和编辑哪些元素可能比单个元素的状态更复杂。这只是一个非常简单的例子。