2011-04-16 118 views
2

我正在處理一個非常巨大的XML文件,4 GB,我總是得到一個內存不足錯誤,我的java堆已經達到最大,這是爲什麼代碼:SAX解析器爲一個非常巨大的XML文件

Handler h1 = new Handler("post"); 
     Handler h2 = new Handler("comment"); 
     posts = new Hashtable<Integer, Posts>(); 
     comments = new Hashtable<Integer, Comments>(); 
     edges = new Hashtable<String, Edges>(); 
     try { 
       output = new BufferedWriter(new FileWriter("gephi.gdf")); 
       SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); 
       SAXParser parser1 = SAXParserFactory.newInstance().newSAXParser(); 


       parser.parse(new File("G:\\posts.xml"), h1); 
       parser1.parse(new File("G:\\comments.xml"), h2); 
      } catch (Exception ex) { 
       ex.printStackTrace(); 
      } 

    @Override 
     public void startElement(String uri, String localName, String qName, 
        Attributes atts) throws SAXException { 
       if(qName.equalsIgnoreCase("row") && type.equals("post")) { 
        post = new Posts(); 
        post.id = Integer.parseInt(atts.getValue("Id")); 
        post.postTypeId = Integer.parseInt(atts.getValue("PostTypeId")); 
        if (atts.getValue("AcceptedAnswerId") != null) 
         post.acceptedAnswerId = Integer.parseInt(atts.getValue("AcceptedAnswerId")); 
        else 
         post.acceptedAnswerId = -1; 
        post.score = Integer.parseInt(atts.getValue("Score")); 
        if (atts.getValue("OwnerUserId") != null) 
         post.ownerUserId = Integer.parseInt(atts.getValue("OwnerUserId")); 
        else 
         post.ownerUserId = -1; 
        if (atts.getValue("ParentId") != null) 
         post.parentId = Integer.parseInt(atts.getValue("ParentId")); 
        else 
         post.parentId = -1; 
       } 
       else if(qName.equalsIgnoreCase("row") && type.equals("comment")) { 
        comment = new Comments(); 
        comment.id = Integer.parseInt(atts.getValue("Id")); 
        comment.postId = Integer.parseInt(atts.getValue("PostId")); 
        if (atts.getValue("Score") != null) 
         comment.score = Integer.parseInt(atts.getValue("Score")); 
        else 
         comment.score = -1; 
        if (atts.getValue("UserId") != null) 
         comment.userId = Integer.parseInt(atts.getValue("UserId")); 
        else 
         comment.userId = -1; 
       } 
      } 



public void endElement(String uri, String localName, String qName) 
     throws SAXException { 
      if(qName.equalsIgnoreCase("row") && type.equals("post")){ 
       posts.put(post.id, post); 
       //System.out.println("Size of hash table is " + posts.size()); 
      }else if (qName.equalsIgnoreCase("row") && type.equals("comment")) 
       comments.put(comment.id, comment); 
     } 

有沒有什麼辦法可以優化這段代碼,使我不會耗盡內存?可能使用流?如果是的話,你會怎麼做?

+0

如果您不喜歡SAX編碼風格,而希望能夠使用XPath,則還有另一個選項,稱爲擴展VTD-XML ...它執行部分XML加載以節省內存..並且它是高性能的。 ..這裏是一篇論文http://sdiwc.us/digitlib/journal_paper.php?paper=00000582.pdf – 2016-04-07 17:35:26

回答

3

SAX解析器對故障有效。

帖子,評論和邊緣HashMaps立即跳出我作爲潛在的問題。我懷疑你需要定期從內存中清空這些地圖以避免OOME。

+3

是啊......讓我們在內存中構建巨大的數據結構,但是歸咎於SAX。 – 2011-04-16 03:57:22

+0

你如何定期沖洗那些? – aherlambang 2011-04-16 04:08:32

+0

@EquinoX要刷新,您需要暫停每個X元素並將數據寫出到JVM之外的某個位置(例如數據庫,磁盤文件等),並清除下一批的映射。 – 2011-04-16 04:37:21