Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 巨大的XML文件:我是否每次读取一个“页面”并处理它?_Java_Xml_Sax - Fatal编程技术网

Java 巨大的XML文件:我是否每次读取一个“页面”并处理它?

Java 巨大的XML文件:我是否每次读取一个“页面”并处理它?,java,xml,sax,Java,Xml,Sax,我需要处理一个巨大的XML文件,4G。我使用了dom4j SAX,但编写了自己的DefaultElementHandler。代码框架如下: SAXParserFactory sf = SAXParserFactory.newInstance(); SAXParser sax = sf.newSAXParser(); sax.parse("english.xml", new DefaultElementHandler("page"){ public void processEle

我需要处理一个巨大的XML文件,4G。我使用了dom4j SAX,但编写了自己的DefaultElementHandler。代码框架如下:

SAXParserFactory sf = SAXParserFactory.newInstance();   
SAXParser sax = sf.newSAXParser();   
sax.parse("english.xml", new DefaultElementHandler("page"){   
public void processElement(Element element) { 
// process the element
}
});    

我以为我在一页一页地处理这个巨大的文件。但似乎不是,因为我总是有内存不足的错误。我错过了什么重要的事情吗?谢谢我不熟悉XML过程

实际上,您并不是按照页面来处理XML,但是如果您扩展了XMLFilterImpl而不是使用DefaultElementHandler,那么您可以简单地处理XML元素。您将进行流式处理,因此在实际操作中不会出现整个文档都在内存中的情况

实际上,您将在元素的开头、属性、元素中的文本中调用事件元素,然后在元素的结尾查看ContentHandler接口中的方法。在处理这些调用的基础上,您可能需要一些数据结构,以便在页面元素中积累元素。还要注意的是,不能保证您只会得到一次文本调用,这取决于解析器


这有助于让它更清晰吗?

我认为它只读取元素中的所有内容,因为我刚刚在网上学习了一个示例

公共抽象类DefaultElementHandler扩展了DefaultHandler{ 私有布尔开始; 私有字符串标记名; 私人架线工

public DefaultElementHandler(String tagName) {
    this.tagName = tagName;
    this.begin = false;
    this.sBuilder = new StringBuilder();
}

public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    if (qName.equals(tagName)||begin){
        sBuilder.append("<");
        sBuilder.append(qName);
        sBuilder.append(" ");
        int attrCount = attributes.getLength();
        for (int i=0; i<attrCount; i++) {
            sBuilder.append(attributes.getQName(i));
            sBuilder.append("=\"");
            sBuilder.append(attributes.getValue(i));
            sBuilder.append("\" ");
        }
        sBuilder.append(">");
        begin = true;
    }
}

public void characters(char[] ch, int start, int length) throws SAXException{       
    StringBuilder sb = new StringBuilder();
    for(int i=0; i < length; i++) {
        sb.append(convertSpecialChar(ch[start+i]));
    }

    String text = sb.toString().trim();      
    //String text = new String(convertSpecialChar(ch), start, length);
    if (text.trim().equals("")) return;
    if (begin) sBuilder.append(text);
}

public void endElement(String uri, String localName, String qName) throws SAXException {
    String stag = "</" + tagName + ">";   
    String ntag = "</" + qName + ">";   
    if (stag.equals(ntag) || begin) {   
        sBuilder.append(ntag);   
        if (stag.equals(ntag)) {   
            begin = false;   
            try {   
                Document doc = DocumentHelper.parseText(sBuilder.toString());   
                Element element = doc.getRootElement();   
                this.processElement(element);   
            } catch (DocumentException e) {   
                e.printStackTrace();  
                System.exit(1);
            }   
            sBuilder.setLength(0);   
        }   
    }   
}

在我看来,您的DefaultElement实现看起来很混乱。它看起来像是sBuilder中的所有内容都在堆积,在找到根元素的结尾之前,它永远不会被清除,或者更可能的是,内存不足

如何读入元素文本取决于需要解析的xml类型。每个元素可以有文本,也可以穿插子元素。一般来说,有web服务和配置文件中看到的xml类型,其中所有元素文本都在叶元素中,然后有一些情况,如XHTML,穿插事情正在发生

如果xml模式的工作方式是所有文本信息都在叶元素中,那么可以缓冲从startElement开始的文本,并在endElement中使用累积的文本,然后清除缓冲区


这里有一篇关于SAX的好文章:

什么是DefaultElementHandler?这不是一个标准类。我自己编写,每次都从DefaultHandlerXML文件格式扩展,我想在一个页面中阅读,包括该元素中的所有内容。DefaultElementHandler实际上做什么呢?很可能这就是使用up所有你的记忆。我在下面的回答中附加了DefaultElementHandler我真的不明白你的意思…请你再详细解释一下好吗?那么如果我想使用前面提到的扩展elementhandler,我做得对还是错。为什么我总是得到OOM?…确保你的sBuilder确实得到重置;你可以使用profi要查看内存发生了什么,或者如果您没有,请放置一些调试代码,以显示sBuilder的行为符合您的预期。检查您在DocumentHelper.parseDocument中实际为DOM提供了什么。清除sBuilder的正确位置在哪里?在elementHandler内部还是外部?应该在内部elementHandler,你不能等待文档的结尾来清除它。我发现它成功地处理了大约1000页,然后它得到了OOM…如何清除sBuilder?sBuilder.setLenghth0?或null?