2017-07-17 1 views
0

Je passais en revue les techniques xml et j'ai décidé d'utiliser SAX sur l'analyseur DOM. Les données, des millions de fichiers XML de près de 6 Ko chacun. J'utilise SAXparser.Analyse de millions de fichiers XML - Java

Je boucle sur tous les fichiers appelant parser.parse (fichier, gestionnaire) un par un mais après 100 000 je reçois un tas d'erreur de mémoire. Quand j'ai essayé de jeter mon tas et de le lire, j'ai vu beaucoup de tableaux et de chaînes de caractères stockés. La question est, comment puis-je analyser des millions de fichiers minuscules sans erreur de tas.

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

Alors, quelle est votre question? – Tavo

+2

Sans regarder votre code, il est difficile de vous aider. Une supposition serait que vous continuez à ouvrir ces fichiers mais vous ne les fermez jamais et libérez les ressources. – alfasin

+1

Avez-vous essayé avec l'analyseur DOM comme vous avez dit que vous analysez fichier par fichier et que chaque fichier est seulement de 6 Ko seulement? Essayez de fermer les connexions xml pour libérer des ressources mémoire – harshavmb

Répondre

2

Tout d'abord, réutilisez SAXParserFactory et l'analyseur lui-même. Créer une SAXParserFactory peut être très coûteux, et créer un analyseur n'est pas bon marché non plus. Pris ensemble, ces opérations prennent probablement beaucoup plus de temps que l'analyse de l'entrée. Mais il s'agit de gagner du temps, pas de la mémoire.

En ce qui concerne la mémoire, je pense que l'espace est entièrement occupé par vos propres structures de données: en particulier la HashMap dans laquelle vous placez les résultats. Essayez d'utiliser JVisualVM pour examiner le tas pour le confirmer. Comme pour la ligne du bas, "comment analyser ces données sans manquer de mémoire", tout dépend de ce que vous voulez faire avec les données. Personne ne paralyse les données XML pour s'amuser; vous le faites parce que vous voulez utiliser les données dans un but précis. Nous ne pouvons pas vous conseiller sur une approche différente sans en savoir plus sur (a) ce que vous voulez faire avec les données, et (b) le volumétrie (vous nous avez donné une large indication d'échelle: mais vous devriez être capable de Dites-nous combien d'entrées vous attendez de cette HashMap, et quelle sera la taille des entrées).

Et une autre petite chose évidente, au cas où vous ne le saviez pas: utilisez l'option -Xmx sur la ligne de commande Java pour contrôler la quantité d'espace disponible.

+0

Au lieu de stocker toutes les valeurs puis de les écrire, j'ai simplement lu et écrit les données une par une. Merci, ça a marché. –

-1

A; fermez les fichiers après que vous avez terminé.

B; Si cela se produit toujours, gardez trace de la mémoire disponible et appelez gc(). Un peu un hack, mais si cela fonctionne ..

C; Si vous avez accès à plusieurs threads, exécutez-le autant que possible; donnez à chaque thread un nombre N et demandez-lui de gérer chaque Nième fichier.

+0

Je n'ouvre jamais de fichier, notez que java.io.File n'a pas de méthode de fermeture parce qu'il n'ouvre pas un fichier mais plutôt un * pointeur vers un fichier? * –

+0

Vous pouvez regarder ce que fait SAXParser pour lire le fichier. Quelque part, le fichier est ouvert, indépendamment de ce qu'il fait. –