2016-01-11 1 views
1

Je veux lire des fichiers texte et convertir chaque mot à un certain nombre. Ensuite, pour chaque fichier, écrivez une séquence de nombres au lieu d'un mot dans un nouveau fichier. J'ai utilisé un HashMap à attribué un seul numéro (identifiant) pour chaque mot, par exemple, le mot pomme est attribué au numéro donc chaque fois, je vois pomme dans un fichier texte que j'écris dans la séquence. Je n'ai besoin que d'une seule HashMap pour éviter d'affecter plus d'un identifiant à un mot. J'ai écrit le code suivant mais il traite le fichier lentement. Par exemple, la conversion d'un fichier texte de taille 165,7 Mo en un fichier de séquence a pris 20 heures. J'ai besoin de convertir 600 fichiers texte avec la même taille pour les fichiers de séquence. Je veux savoir s'il existe un moyen d'améliorer l'efficacité de mon code. La fonction suivante est appelée pour chaque fichier texte.améliorer la vitesse de lecture et d'écriture de gros fichiers avec Buffered écriture/lecteur

public void ConvertTextToSequence(File file) { 
    try{ 

     FileWriter filewriter=new FileWriter(path.keywordDocIdsSequence,true); 
     BufferedWriter bufferedWriter= new BufferedWriter(filewriter); 

     String sequence=""; 
     FileReader fileReader = new FileReader(file); 
     BufferedReader bufferedReader = new BufferedReader(fileReader); 
     String line = bufferedReader.readLine(); 
     while(line!=null) 
     { 
      StringTokenizer tokens = new StringTokenizer(line); 

        String str; 
        while (tokens.hasMoreTokens()) 
        { 
         str = tokens.nextToken(); 
         if(keywordsId.containsKey(str)) 
           sequence= sequence+" "+keywordsId.get(stmWord); 
         else 
         { 
           keywordsId.put(str,id); 
           sequence= sequence+" "+id; 
           id++; 
          } 


         if(keywordsId.size()%10000==0) 
         { 
           bufferedWriter.append(sequence); 
           sequence=""; 

           start=id; 
         } 

        } 
        String line = bufferedReader.readLine(); 
       } 
     } 

     if(start<id) 
     { 

       bufferedWriter.append(sequence); 
     } 

     bufferedReader.close(); 
     fileReader.close(); 

     bufferedWriter.close(); 
     filewriter.close(); 
    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 

}

Le constructeur de cette classe est:

public ConvertTextToKeywordIds(){ 
    path= new LocalPath(); 
    repository= new RepositorySQL(); 
    keywordsId= new HashMap<String, Integer>(); 
    id=1; 
    start=1;} 
+2

Ce code ne serait pas compilé. Si vous voulez vous dire pourquoi votre code réel est lent, postez votre vrai code. Ce que je peux déjà dire est que l'ajout à une chaîne et l'attente de la carte pour avoir 10000 éléments avant d'écrire la chaîne à l'écrivain est très, très productif. Ecrire directement à l'écrivain, et laissez-le faire son travail: mise en mémoire tampon. –

+0

@JBNizet mon vrai code est vraiment gros et compliqué car je nettoie chaque jeton avant de l'insérer dans HashMap. Je résous une erreur dans mon code je pense que vous pouvez compiler la fonction maintenant. – Suri

Répondre

2

Je soupçonne que la vitesse de votre programme est lié au ressassement de la carte de hachage comme le nombre de mots se développe. Chaque rehash peut subir une pénalité de temps significative à mesure que la taille de la carte de hachage augmente. Vous pouvez essayer d'estimer le nombre de mots uniques que vous attendez et l'utiliser pour initialiser la carte de hachage.

Comme l'a mentionné @JB Nizet vous pouvez écrire directement à l'écrivain tampon plutôt que d'attendre d'accumuler un certain nombre d'entrées. Étant donné que le writer tamponné est déjà configuré pour écrire uniquement lorsqu'il a accumulé suffisamment de modifications.

1

Votre boost de performance le plus efficace utilise probablement StringBuilder au lieu de String pour votre sequence.

Je voudrais également écrire et vider le sequence chaque fois qu'il dépasse une certaine longueur plutôt que lorsque vous avez ajouté 10000 mots à votre carte.

Cette carte pourrait être assez grand - avez-vous pensé améliorer cela? Si vous touchez des millions d'entrées, vous pouvez obtenir de meilleures performances en utilisant une base de données.

+0

Merci pour vos suggestions. Pourquoi suggérez-vous StringBuilder au lieu de String? Je dois avoir toutes les informations dans la mémoire principale, donc je ne peux pas utiliser la base de données. – Suri

+0

@Suri - La concaténation 'String' est très coûteuse -' StringBuilder' est conçu pour être bien meilleur en concaténation. – OldCurmudgeon

+1

@Suri - Voir [String builder vs chaîne de concaténation] (http://stackoverflow.com/q/18453458/823393) pour discussion. – OldCurmudgeon