【问题标题】:How to read large XML file consisting of large number of small items efficiently in Java?如何在 Java 中有效地读取由大量小项目组成的大型 XML 文件?
【发布时间】:2010-09-06 18:09:09
【问题描述】:

我有一个较大的 XML 文件,其中包含相对固定大小的项目,即

<rootElem>
  <item>...</item>

  <item>...</item>
  <item>...</item>
<rootElem>

item 元素相对较浅且通常较小(

如何在 Java 中有效地处理文件?我无法将整个文件作为 DOM 读取,而且我不喜欢使用 SAX,因为代码变得相当复杂。我想避免将文件分成更小的部分。

如果我可以一次获得每个 item 元素,作为一个单独的 DOM 文档,我可以使用 JAXB 之类的工具对其进行处理,这是最佳选择。基本上我只想循环遍历所有项目。

我认为这是一个相当普遍的问题。

【问题讨论】:

    标签: java xml parsing dom sax


    【解决方案1】:

    Java 6 有一个StAX support。它执行类似于 SAX 的流处理,但使用基于拉取的方法,从而使处理代码更简单。

    【讨论】:

      【解决方案2】:

      当输入很大时,通常需要对文档进行顺序(也称为流)处理。确实,SAX 可能会变得有点混乱(或者至少需要相当多的代码),因为您基本上必须构建一个状态机来进行提取。如果您寻找 XML 拉解析器而不是基于事件的实现,您至少会发现这种方法更易于使用。

      您提取项目元素内容的想法也是可行的,第一步使用 SAX,并且可能会在使用事件/拉解析和完全 DOM 访问的灵活性之间取得可接受的平衡。 (它仍然会比 event/pull 解析慢得多,进行大量分配,但至少取消了将所有内容同时保存在内存中的要求。)

      【讨论】:

      • @axtavt 已经给出了建议。我曾经使用过xmlpull.org,但现在不确定它的状态。
      【解决方案3】:

      我没有尝试过,但是...如果您的 XML 文件始终具有相同的格式,您可以使用 BufferedReader 自己解析它们,寻找&lt;item&gt; 标签,并将项目内容存储在 StringBuffer 中。然后,您可以使用 DOM 解析器解析每个字符串(包括作为根的项目),并对其进行处理。您只需要一个 DocumentBuilder 即可处理所有项目。

      该方法的优点是您可以快速解析文件而没有任何内存问题,并且具有 DOM 树的便利性。缺点是您不会进行真正的 XML 解析:如果 XML 不是您所期望的(&lt;item/&gt; 可能吗?),您的程序可能会崩溃。

      这里的问题是,当您第一次解析文件时,您需要将一些 XML 元素(项目内的元素)视为不是 XML 元素。如果您能找到另一种方法,您可以使用 SAX 解析文件,以安全的方式将项目内容作为字符串获取,然后使用 DOM 解析器解析项目,如上所述。

      我想另一种选择是使用 SAX 或 StAX 并根据相关事件为项目创建 DOM 树。但如果语言中有很多元素,它可能会很复杂。

      【讨论】:

        【解决方案4】:

        使用 DOM,我有一种有效的解析 xml 的方法。我自己准备了这个 DOM 解析器,使用递归来解析你的 xml,而无需了解单个标签。如果存在,它将按顺序为您提供每个节点的文本内容。您也可以删除以下代码中的注释部分以获取节点名称。希望对您有所帮助。

        import java.io.BufferedWriter;
        import java.io.File;  
        import java.io.FileInputStream;  
        import java.io.FileOutputStream;
        import java.io.IOException;
        import java.io.OutputStreamWriter;
        
         import javax.xml.parsers.DocumentBuilder;  
         import javax.xml.parsers.DocumentBuilderFactory;  
         import org.w3c.dom.Document;  
         import org.w3c.dom.Node;  
         import org.w3c.dom.NodeList;  
        
        
        
        public class RecDOMP {
        
        
        public static void main(String[] args) throws Exception{
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();  
                dbf.setValidating(false); 
                DocumentBuilder db = dbf.newDocumentBuilder();   
        
        // replace following  path with your input xml path  
                 Document doc = db.parse(new FileInputStream(new File  ("D:\\ambuj\\input.xml")));  
        
        // replace following  path with your output xml path 
                 File OutputDOM = new File("D:\\ambuj\\outapip1.txt");
                    FileOutputStream fostream = new FileOutputStream(OutputDOM);
                    OutputStreamWriter oswriter = new OutputStreamWriter (fostream);
                    BufferedWriter bwriter = new BufferedWriter(oswriter);
        
                    // if file doesnt exists, then create it
                    if (!OutputDOM.exists()) {
                        OutputDOM.createNewFile();}
        
        
                    visitRecursively(doc,bwriter);
                    bwriter.close(); oswriter.close(); fostream.close();
        
                    System.out.println("Done");
        }
        public static void visitRecursively(Node node, BufferedWriter bw) throws IOException{  
        
                     // get all child nodes  
                 NodeList list = node.getChildNodes();                                  
                 for (int i=0; i<list.getLength(); i++) {          
                         // get child node              
               Node childNode = list.item(i);  
               if (childNode.getNodeType() == Node.TEXT_NODE)
               {
           //System.out.println("Found Node: " + childNode.getNodeName()           
            //   + " - with value: " + childNode.getNodeValue()+" Node type:"+childNode.getNodeType()); 
        
           String nodeValue= childNode.getNodeValue();
           nodeValue=nodeValue.replace("\n","").replaceAll("\\s","");
           if (!nodeValue.isEmpty())
           {
               System.out.println(nodeValue);
               bw.write(nodeValue);
               bw.newLine();
           }
               }
               visitRecursively(childNode,bw);  
        
                    }         
        
             }  
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-08-30
          • 1970-01-01
          • 2022-07-21
          • 2011-12-27
          • 1970-01-01
          相关资源
          最近更新 更多