我凌驾于
public void characters(char[] ch,
int start,
int length)
throws SAXException
解析XML文档时。它适用于小型XML文档(1MB或更少)。但是,如果XML文档是100MB或更多)我开始在此函数内获取java堆空间内存错误。
在做了一些研究之后here我意识到上面的字符数组“ch”的大小取决于“startElement()”和“endElement()”之间的字符数。
所以我想知道,是否有一种智能方法可以覆盖“startElement”和“endElement”以返回较小的数据块?
例如,假设我有一个XML文件,如下所示:
<element1>
This is a very simple sentence that is not very long.
</element1>
目前“characters()”函数将返回“这是一个非常简单的句子,不会很长。”作为一个块。
但我的问题是如果XML文件如下:
<element1>
An entire book's worth of content is pasted in this single element. Possibly millions of characters.
</element1>
有没有办法可以“欺骗”startElement()和endElement()让characters()函数返回整本书的书籍内容?
答案 0 :(得分:1)
您无法欺骗 SAX解析器,以较小的块为您的ContentHandler
提供字符数据。解析器已被允许以小于元素的整个内容的块的形式提供它,然而,当内容很大时,我希望这是它们的正常行为。否则将要求他们在内部缓冲潜在的大量数据,无特殊原因。
如果您发现您的特定解析器确实提供了比您想要的更大的块,那么您应该查阅其文档。您可以设置一个选项来影响它。否则,您的另一种选择是找到或制作一个您更喜欢其行为的解析器。
但是,请检查一下你的事实。可能是解析器确实以合理大小的块返回数据,而问题实际上就在于您正在使用它们。特别是,如果要构建整个文件的某种内存表示形式,那么接收它的大小几乎不重要。
还要考虑增加VM的最大堆大小。一个100MB的文件并不是非常庞大,但是你的虚拟机可能会受到堆大小限制的影响,而这个限制对于这个问题来说是不切实际的低。
答案 1 :(得分:0)
非常老的线程,但是最近我不得不处理类似的任务,因此发布我的答案对其他一些人可能很有用。我认为后期Java版本jdk 9具有读取字符数据块的功能,您只需要设置CDATA_CHUNK_SIZE,即可在Stax和Sax解析器中使用。
import java.io.FileInputStream;
import java.io.InputStream;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
public class SaxDemo {
final static String CDATA_CHUNK_SIZE = "jdk.xml.cdataChunkSize";
public static void main(String argv[]) {
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader reader = sp.getXMLReader();
reader.setContentHandler(new TestHandler());
try (InputStream is = new FileInputStream("FileDir/file")) {
reader.setProperty(CDATA_CHUNK_SIZE, 10000);
reader.parse(new InputSource(is));
System.out.println("Done");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}