朋友我需要你的帮助,我必须处理一个包含大量信息的大文件(关于文件的重量为30 Mb)。处理此信息文件时,java给出了这个错误:
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2367)
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:130)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:114)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:535)
at java.lang.StringBuffer.append(StringBuffer.java:322)
at java.io.StringWriter.write(StringWriter.java:94)
at java.io.Writer.write(Writer.java:127)
at com.sun.org.apache.xml.internal.serialize.Printer.printText(Printer.java:170)
.....
我的代码是:
...
public Document generateXML(File file, String type) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
Document document = docBuilder.newDocument();
Element rootElement = document.createElement("data");
document.appendChild(rootElement);
Element informacionElement = document.createElement("information");
rootElement.appendChild(informacionElement);
Element entityElement = document.createElement("entity");
entityElement.appendChild(document.createTextNode("ANYTHING"));
informacionElement.appendChild(entityElement);
Element entityCode = document.createElement("code");
entityCode.appendChild(document.createTextNode(0000));
informacionElement.appendChild(entityCode);
Element fileElement = document.createElement("FILENAME");
fileElement.appendChild(document.createTextNode(file.getName()));
informacionElement.appendChild(fileElement);
Element detailElement = document.createElement("detail");
rootElement.appendChild(detailElement);
Path path = Paths.get(file.getAbsolutePath());
Scanner tmpFile = new Scanner(path, StandardCharsets.UTF_8.name());
String[] tmpTags = keyXml.get(type);
int row = 1;
while (tmpFile.hasNextLine()) {
Element rowElement = document.createElement("row");
filaElement.setAttribute("id", Integer.toString(row));
Scanner tmpLine = new Scanner(tmpFile.nextLine());
tmpLine.useDelimiter("\\|");
int index = 0;
while (tmpLine.hasNext()) {
Element element = document.createElement(tmpTags[index]);
String text = tmpLine.next().trim();
element.appendChild(document.createTextNode(text));
filaElement.appendChild(element);
++index;
}
detailElement.appendChild(filaElement);
++fila;
}
return document;
} catch (ParserConfigurationException | IOException ex) {
Logger.getLogger(HandlerXML.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
...
此代码生成以下XML文档:
<data>
<information>
<entity>ANYTHING</entity>
<code>0000</code>
<filename>filename_XXX</filename>
</information>
<detail>
<row id="1">
<tag1>0099</tag1>
<tag2>2014</tag2>
<tag3>05</tag3>
<tag4>0015</tag4>
<tag5>06</tag5>
<tag6>06</tag6>
<tag7>000000000099907</tag7>
<tag8>098026</tag8>
<tag9>00000781.40</tag9>
<tag10>E</tag10>
<tag11>000000006804750</tag11>
<tag12>xxx</tag12>
<tag13>xxxx</tag13>
<tag14>xxx</tag14>
<tag15></tag15>
<tag16></tag16>
<tag17>xx</tag17>
<tag18>xxx</tag18>
<tag19>1014</tag19>
<tag20>05</tag20>
<tag21>11111</tag21>
<tag22>1014</tag22>
<tag23>00000000000000000000</tag23>
<tag24>3</tag24>
<tag25>20101</tag25>
<tag26>00000000</tag26>
<tag27>46671</tag27>
<tag28>1</tag28>
<tag29>N</tag29>
<tag30></tag30>
<tag31></tag31>
<tag32>A</tag32>
<tag33></tag33>
<tag34></tag34>
<tag35></tag35>
<tag36></tag36>
<tag37></tag37>
<tag38></tag38>
</row>
............
</detail>
</data>
获取xml数据的词是:
** 0099 | 2014 | 05 | 0015 | 06 | 06 | 00000000003101 | 066671 | 000077777.00 | E | 000000002719415 | xxx | xxxxxx | xxxxxxxx | | | xxxxxx | | 1014 | 05 | 12254758 | 1014 | 00000000000000000000 | 3 | 20101 | 00000000 | 748596 | 1 | X | | | Q | | | | | **
现在假设必须为100000行信息生成xml,如果您想知道,必须将所有行转换为XML格式。
问题是,当你将对象转换为 STRING 到 DOCUMENT 时,我得到了我之前显示的错误,我用来转换 DOCUMENT的函数到 STRING 是:
private static String convertDocumentToString(Document doc) {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer;
try {
transformer = tf.newTransformer();
StringWriter writer = new StringWriter();
transformer.transform(new DOMSource(doc), new StreamResult(writer));
return writer.getBuffer().toString();
}
catch (TransformerException e) {}
return "";
}
现在这个错误是虚拟内存,java VM的解决方法是用 -Xmx #### m 来增加内存,但是我想知道这是否通过其他方式解决了,试着处理数据type with:String,StringBuilder和byte。有谁能解决这个问题?
提前致谢。
答案 0 :(得分:2)
&#34; 30 MB&#34;并不是那么大。
建议:将其添加到Java命令行:-XX:MaxPermSize=512m
ALSO:
绝对熟悉Java分析器jvisualvm。它附带JDK。
以下是解决此类问题的好文章:Anatomy of a PermGen Memory Leak
&#39;希望有所帮助!
答案 1 :(得分:1)
&#34;一个非常大的文件&#34;并不表示您的程序将使用大量内存。它更可能意味着您可能花费相当多的时间来处理文件,但实际上与您使用的空间无关。
只有文件的当前相关部分应保留在内存中。
答案 2 :(得分:1)
但是quies知道这是否通过其他方式解决了
是的,当然还有另一种方法:在序列化XML时,不要使用StringWriter
作为目标。如果您希望XML最终存储在文件中,请为其创建适当的FileWriter
,并将其交给您的XML序列化代码。
如果您从异常的堆栈跟踪中包含更多内容,我可能能够为您提供比上述更精确的建议。产生异常的实际代码也会有所帮助。