2017-07-17 2 views
0

Ich ging durch Parsing XML-Techniken und entschied mich, SAX über DOM-Parser zu verwenden. Die Daten, Millionen von XML-Dateien von jeweils fast 6KB. Ich benutze SAXparser.Parsing Millionen von XML-Dateien - Java

Ich Schleife über alle Dateien parser.parse (Datei, Handler) einzeln aufrufen, aber nach 100.000 bekomme ich einen Heap nicht genügend Speicherfehler. Als ich versuchte, meinen Heap zu löschen und zu lesen, sah ich viele Char-Arrays und Strings gespeichert.

Die Frage ist, wie kann ich durch Millionen von kleinen Dateien ohne Heap-Fehler analysieren.

import javax.xml.parsers.*; 
import org.xml.sax.*; 
import org.xml.sax.helpers.*; 
import java.util.*; 
import java.io.*; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

/** 
* 
* @author Ajinkya Jumbad 
*/ 
public class dataset { 

    static List<String> cols; 
    public HashMap<String, HashMap> hm = new HashMap<>(); 
    static int i =0; 

    dataset() { 
     String coln[] = { 
      "UID", 
      "Name", 
      "NationID", 
      "Born", 
      "Age", 
      "IntCaps", 
      "IntGoals", 
      "U21Caps", 
      "U21Goals", 
      "Height", 
      "Weight", 
      "AerialAbility", 
      "CommandOfArea", 
      "Communication", 
      "Eccentricity", 
      "Handling", 
      "Kicking", 
      "OneOnOnes", 
      "Reflexes", 
      "RushingOut", 
      "TendencyToPunch", 
      "Throwing", 
      "Corners", 
      "Crossing", 
      "Dribbling", 
      "Finishing", 
      "FirstTouch", 
      "Freekicks", 
      "Heading", 
      "LongShots", 
      "Longthrows", 
      "Marking", 
      "Passing", 
      "PenaltyTaking", 
      "Tackling", 
      "Technique", 
      "Aggression", 
      "Anticipation", 
      "Bravery", 
      "Composure", 
      "Concentration", 
      "Vision", 
      "Decisions", 
      "Determination", 
      "Flair", 
      "Leadership", 
      "OffTheBall", 
      "Positioning", 
      "Teamwork", 
      "Workrate", 
      "Acceleration", 
      "Agility", 
      "Balance", 
      "Jumping", 
      "LeftFoot", 
      "NaturalFitness", 
      "Pace", 
      "RightFoot", 
      "Stamina", 
      "Strength", 
      "Consistency", 
      "Dirtiness", 
      "ImportantMatches", 
      "InjuryProness", 
      "Versatility", 
      "Adaptability", 
      "Ambition", 
      "Loyalty", 
      "Pressure", 
      "Professional", 
      "Sportsmanship", 
      "Temperament", 
      "Controversy", 
      "PositionsDesc", 
      "Goalkeeper", 
      "Sweeper", 
      "Striker", 
      "AttackingMidCentral", 
      "AttackingMidLeft", 
      "AttackingMidRight", 
      "DefenderCentral", 
      "DefenderLeft", 
      "DefenderRight", 
      "DefensiveMidfielder", 
      "MidfielderCentral", 
      "MidfielderLeft", 
      "MidfielderRight", 
      "WingBackLeft", 
      "WingBackRight"}; 
     cols = Arrays.asList(coln); 
     try { 
      File f = new File("C:\\Users\\Ajinkya Jumbad\\Desktop\\fmdata"); 

      //File files[] = f.listFiles(); 
      for (File file : f.listFiles()) { 
       //System.out.println(file.getAbsolutePath()); 
       if (file.isFile()) { 
        parse p = new parse(file); 
       } 
      } 


      //savefile(); 
     } catch (Exception ex) { 
      Logger.getLogger(dataset.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    private void savefile() { 
     try { 
      String file_name = "dataset.csv"; 
      FileWriter w = new FileWriter(file_name); 
      writecsv ws = new writecsv(); 
      boolean first = true; 
      StringBuilder sb = new StringBuilder(); 
      for (String key : cols) { 
       if (!first) { 
        sb.append(","); 
       } 
       sb.append(key); 
       first = false; 
      } 
      sb.append("\n"); 
      w.append(sb.toString()); 
      for (String uid : hm.keySet()) { 
       ws.writeLine(w, hm.get(uid)); 
      } 
      w.close(); 
     } catch (Exception e) { 
      System.out.println(e.getMessage()); 
     } 
    } 

    public class parse{ 
     parse(File file){ 
      try { 
       SAXParserFactory parserfac = SAXParserFactory.newInstance(); 
       parserfac.setNamespaceAware(true); 
       SAXParser parser = parserfac.newSAXParser(); 
       DefaultHandler handler = new DefaultHandler(){ 
        HashMap<String, String> ht; 
        @Override 
        public void startDocument() { 
         ht = new HashMap<>(); 
        } 

        @Override 
        public void startElement(String namespaceURI, 
          String localName, 
          String qName, 
          Attributes atts) { 
         if (atts.getValue("Value") != null && cols.contains(localName)) { 
          //System.out.println(localName); 
          String key = localName; 
          ht.put(key, atts.getValue("Value")); 
         } 
        } 

        @Override 
        public void endDocument() { 
         String uid = ht.get("UID"); 
         hm.put(uid, ht); 
         dataset.i += 1; 
         if(dataset.i%100 == 0){ 
          System.out.println(dataset.i); 
         } 
        } 

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

        } 

       }; 
       parser.parse(file, handler); 
      } catch (Exception ex) { 
       Logger.getLogger(dataset.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    } 

    public static void main(String[] args) { 
     dataset ds = new dataset(); 
    } 

} 
+1

Was ist Ihre Frage? – Tavo

+2

Ohne auf Ihren Code zu schauen, ist es schwierig, Ihnen zu helfen. Eine Vermutung wäre, dass Sie diese Dateien weiterhin öffnen, aber niemals schließen und Ressourcen freigeben. – alfasin

+1

Haben Sie mit dem DOM-Parser versucht, wie Sie sagten, dass Sie Datei für Datei analysieren und jede Datei nur 6 KB groß ist? Versuchen xml Verbindungen zu schließen mein Code, um Speicher-Ressourcen – harshavmb

Antwort

2

Verwenden Sie zuerst die SAXParserFactory und den Parser selbst. Das Erstellen einer SAXParserFactory kann sehr teuer sein, und das Erstellen eines Parsers ist auch nicht billig. Zusammengenommen dauern diese Operationen wahrscheinlich viel länger als das tatsächliche Parsen der Eingabe. Aber das ist Zeit sparen, nicht Speicher.

Soweit Speicher betroffen ist, vermute ich, dass der Raum mit Ihren eigenen Datenstrukturen belegt ist: speziell die HashMap, in die Sie die Ergebnisse bringen. Versuchen Sie, JVisualVM zu verwenden, um den Heapspeicher zu überprüfen, um dies zu bestätigen.

Was die untere Zeile betrifft, "wie analysiere ich diese Daten, ohne den Speicher zu leeren", hängt alles davon ab, was Sie mit den Daten machen wollen. Niemand analysiert XML-Daten zum Spaß; Sie tun es, weil Sie die Daten für einen bestimmten Zweck verwenden möchten. Wir können Sie nicht über einen anderen Ansatz beraten, ohne mehr darüber zu wissen, was Sie mit den Daten machen wollen, und (b) die Volumetrie (Sie haben uns einen breiten Maßstab für die Skalierung gegeben: aber Sie sollten es können sagen Sie uns, wie viele Einträge diese HashMap enthalten soll und wie groß die Einträge sein werden.

Und noch eine andere kleine Sache, falls Sie sich dessen nicht bewusst waren: Verwenden Sie die Option -Xmx in der Java-Befehlszeile, um den verfügbaren Heap-Speicherplatz zu steuern.

+0

Anstatt alle Werte zu speichern und sie dann zu schreiben, lese und schreibe ich einfach die Daten einzeln. Danke, es hat funktioniert. –

-1

A; Schließen Sie die Dateien, nachdem Sie fertig sind.

B; Wenn es immer noch passiert, verfolge den freien Speicher und rufe gc() auf. Art von einem Hack, aber wenn es funktioniert ..

C; Wenn Sie Zugriff auf mehrere Threads haben, führen Sie diese so oft wie möglich aus. geben Sie jedem Thread eine Zahl N und behandeln Sie jede N-te Datei.

+0

ich nie geöffnete Datei, beachten Sie, dass i java.io.File keine enge Methode hat, weil es nicht wirklich eine Datei öffnen, nicht eher ist es ein * Zeiger auf eine Datei? * –

+0

Sie können wollen, betrachten, was SAXParser zu lesen tut die Datei. Irgendwo wird die Datei geöffnet, unabhängig davon, was sie gerade macht. –