在将大量文件数据写入XML时减少内存(RAM)消耗的有效方法



我必须将7个列表写入XML文件,每个列表的大小为1gb到5gb。

期望输出的XML文件如下:

<doc>
<items1>
<itemA>..</itemA>
..
</items1>
<items2>
<itemB>..</itemB>
..
</items2>
<items3>
<itemC>..</itemC>
..
</items3>
.
.
.
<items7>
<itemG>..</itemG>
..
</items7>
</doc>  

Java对象如下:

List<ItemA> items1 = new List<>(); // 1GB-5GB
List<ItemB> items2 = new List<>(); // 1GB-5GB
List<ItemC> items3 = new List<>(); // 1GB-5GB
List<ItemD> items4 = new List<>(); // 1GB-5GB
List<ItemE> items5 = new List<>(); // 1GB-5GB
List<ItemF> items6 = new List<>(); // 1GB-5GB
List<ItemG> items7 = new List<>(); // 1GB-5GB

将所有列表包装成单个对象(目录)到Java对象中,并且一次编组会消耗大量内存,并且每次当列表大小增加时,我们都必须扩展基础设施。下面是代码:

JAXBContext.newInstance("ta").createMarshaller().marshal(new ObjectFactory().createCatalogue(catalogue), new FileOutputStream(fileName));

这里的catalog是一个Java对象,包含了所有7个列表。

有什么聪明的方法可以减少内存消耗,通过写数据块。我为此探索了stax,但我无法找到编写数据列表的方法。

在Java中是否有办法以一种有效的方式将高达20 GB的内存写入XML,而不需要在基础设施上扩展RAM ?

我们想要分别写每个列表,并且以前写的文件不应该在写下一个列表时加载到堆中。

使用StAX很可能是最好的方法,这不仅是因为您不必将整个XML文档保存在内存中,而且还因为您也不必将所有保存在内存中。不知道你从哪里找的StAX编写,但我在Java EE 5教程中找到了以下内容:

下面的示例取自StAX规范,展示了如何实例化输出工厂,创建写入器,并写入XML输出:

XMLOutputFactory output = XMLOutputFactory.newInstance();
XMLStreamWriter writer = output.createXMLStreamWriter( ... );
writer.writeStartDocument(); 
writer.setPrefix("c","http://c");
writer.setDefaultNamespace("http://c");
writer.writeStartElement("http://c","a");
writer.writeAttribute("b","blah");
writer.writeNamespace("c","http://c");
writer.writeDefaultNamespace("http://c");
writer.setPrefix("d","http://c");
writer.writeEmptyElement("http://c","d");
writer.writeAttribute("http://c","chris","fry");
writer.writeNamespace("d","http://c"); 
writer.writeCharacters("Jean Arp"); 
writer.writeEndElement(); 
writer.flush(); 

此代码生成以下XML(新行是非规范的):

<?xml version=’1.0’ encoding=’utf-8’?> 
<a b="blah" xmlns:c="http://c" xmlns="http://c">
<d:d d:chris="fry" xmlns:d="http://c"/>
Jean Arp
</a> 

编辑:我还注意到,在您发布的链接中有一节是关于使用StAX生成XML的。另外,请注意"编写列表"并没有什么特别之处,您只需遍历列表并为每个条目编写一个标记。像这样:

XMLStreamWriter writer = ...;
writer.writeStartDocument();
writer.writeStartElement("doc");
// Write the first list:
writer.writeStartElement("items1");
for (ItemA e: items1) {
writer.writeStartElement("itemA");
// TODO: Write attributes, sub-elements, text or whatever is needed
writer.writeEndElement();
});
writer.writeEndElement();
// TODO: Write items2, items3, ..., items7 in the same fashion as items1
// Close document
writer.writeEndElement();
writer.writeEndDocument();

XMLStreamWriter是低级的,这意味着除了将XML写入流之外,它不会为您做更多的事情,但它并不复杂。因此,您最终可能会比使用JAXB时多出几行代码,但是您必须编写的代码不会特别难编写。

最新更新