【问题标题】:Does SAX Parser keeps all data in Memory?SAX Parser 是否将所有数据保存在内存中?
【发布时间】:2019-03-12 19:27:31
【问题描述】:

我正在处理一个需求,我需要拆分大型 XML 并进一步处理。

这里是 XML 示例,它可以变成单行。

<?xml version="1.0"?><company><staff><firstname>yong</firstname><firstname>jin</firstname></staff></company>

这是我的代码:

import java.util.Arrays;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class ReadXML {

   public static void main(String argv[]) {

    try {

    SAXParserFactory factory = SAXParserFactory.newInstance();
    SAXParser saxParser = factory.newSAXParser();

    DefaultHandler handler = new DefaultHandler() {

    boolean bfname = false;
    boolean blname = false;
    boolean bnname = false;
    boolean bsalary = false;

    public void startElement(String uri, String localName,String qName, 
                Attributes attributes) throws SAXException {

        System.out.println("Parameters :" + uri +":"+ localName +":"+ qName +":"+ attributes);
        System.out.println("Start Element :" + qName);

        if (qName.equalsIgnoreCase("FIRSTNAME")) {
            bfname = true;
        }

        if (qName.equalsIgnoreCase("LASTNAME")) {
            blname = true;
        }

        if (qName.equalsIgnoreCase("NICKNAME")) {
            bnname = true;
        }

        if (qName.equalsIgnoreCase("SALARY")) {
            bsalary = true;
        }

    }

    public void endElement(String uri, String localName,
        String qName) throws SAXException {

        System.out.println("End Element :" + qName);

    }

    public void characters(char[] ch, int start, int length) throws SAXException {

        System.out.println("Im here:"+Arrays.toString(ch));----Line 1
        if (bfname) {
            System.out.println("First Name : " + new String(ch, start, length));
            bfname = false;
        }

        if (blname) {
            System.out.println("Last Name : " + new String(ch, start, length));
            blname = false;
        }

        if (bnname) {
            System.out.println("Nick Name : " + new String(ch, start, length));
            bnname = false;
        }

        if (bsalary) {
            System.out.println("Salary : " + new String(ch, start, length));
            bsalary = false;
        }

    }

     };

       saxParser.parse("C:\\Lenny\\Work\\XML\\SaxParsing_01.xml", handler);



        /*InputSource input = new InputSource("C:\\Lenny\\Work\\XML\\SaxParsing_01.xml");
        System.out.println(input);
        XMLReader reader = saxParser.getXMLReader();
        reader.parse(input);*/


     } catch (Exception e) {
       e.printStackTrace();
     }

   }

}

我的第一个疑问是,SAXParser 是否明智地读取字节?

第二,我想要这样的输出。

<firstname>yong</firstname>
<firstname>jin</firstname>

这件事我可以管理,但想知道..当我得到&lt;firstname&gt; 标签并进入characters 方法的那一刻,为什么它打印所有整个 XML ?它不应该只在Line 1 打印yong 而不是打印整个XML 吗?它全部打印,所以这就是为什么我在想,SAXParser 是否将整个数据保存在内存中?

任何建议请..!

谢谢

【问题讨论】:

    标签: java sax


    【解决方案1】:

    SAX Parser 是否将所有数据保存在内存中?

    不,这就是重点。将 XML 文档的整个 DOM 数据加载到内存中,然后从中提取你想要的东西,比使用 SAX 繁琐的模型要容易得多。

    但 SAX 具有动态读取文档的优点,无需将其完全加载到内存中。

    我的第一个疑问是,SAXParser 是否明智地读取字节?

    不是按字节计算的,不。这将是非常低效的,特别是考虑到 SAX 的目的是对大量文档进行操作。这是一个缓冲读取。并不是说会消耗太多内存。

    为什么要打印整个 XML?它不应该只在 Line 上打印 yong 1 而不是打印整个 XML?它的打印全部,所以这就是为什么我 想一想,SAXParser 是否将整个数据保存在内存中?

    见上文,出于合理的性能原因,SAX 使用缓冲区进行读取。作为 characters() 方法的参数给出的 char[] 大致就是前面提到的缓冲区。

    在您的示例中,您的文档很小,当然它完全适合用于读取文档的真实缓冲区。 如果您要处理更大的文档,您会注意到缓冲区包含数千个字符,但远不及整个文档。

    【讨论】:

    • 因此,如果我的单行 xml 的大小为 1+GB,可能会失败 ....对...?因为我猜 SAXParser 会读取整行并放入内存,然后调用检查标签...正确吗?
    • @Lenny no... 它不读取行。它读取一个缓冲区。它取决于实现,但它会读取 1000 个字节,然后将它们解码为字符并将它们放入 char 缓冲区中。
    猜你喜欢
    • 2015-06-15
    • 1970-01-01
    • 2016-11-11
    • 2020-11-23
    • 2011-10-31
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    相关资源
    最近更新 更多