IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

lecture fichier très lente en java


Sujet :

Langage Java

  1. #1
    Membre à l'essai
    Inscrit en
    Septembre 2010
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 12
    Points : 11
    Points
    11
    Par défaut lecture fichier très lente en java
    Salut

    Voila j'ai développé une application qui me permet de supprimer les doublons d'un fichiers textes.

    le problème c'est que quand je le lance avec des gros fichier (4 millions de lignes- 70Mo) ça prend énormément de temps plus de 48h.

    j'utilise Bufferreader pour lire le fichier,je vérifie la validité de mes données et je réécrit mes resultats dans un autre fichier.

    quelqu'un aurai une idée pour diminuer le temps de traitement?

  2. #2
    Membre chevronné
    Avatar de CheryBen
    Inscrit en
    Mai 2005
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 599
    Points : 2 197
    Points
    2 197
    Par défaut
    Bonjour, 48h ça parait énorme. Il est difficile de dire comment diminuer le temps de traitement sans connaitre le code. Peux-tu le poster? (sans oublier la balise code)

    La plupart du temps pour optimiser, il faut chercher du côté de l'algorithme utilisé. Il faut aussi éviter d'utiliser certaines classes synchronisées inutilement comme Vector ou HashTable.

  3. #3
    Membre éprouvé
    Inscrit en
    Mars 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Mars 2006
    Messages : 848
    Points : 1 078
    Points
    1 078
    Par défaut
    Il faut aussi éviter la concaténation de String et utiliser des StringBuilder.

    C'est une erreur assez courante qui produit ce genre d'effets.

  4. #4
    Membre à l'essai
    Inscrit en
    Septembre 2010
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 12
    Points : 11
    Points
    11
    Par défaut
    merci pour votre réponse,voila je met une partie du code qui fait le traitement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    BufferedReader reader = new BufferedReader(new FileReader(chemin));
                BufferedReader reader2 = new BufferedReader(new FileReader(chemin6));
     
                FileWriter fstream = new FileWriter("c:\\out-"+nomfichier+"-"+dat+".txt");
                BufferedWriter out = new BufferedWriter(fstream);
     
                String line = "";
                String line2 = "";
     
                while ((line2=reader.readLine()) != null) {
                    String masque = "^[a-zA-Z]+[a-zA-Z0-9\\._-]*[a-zA-Z0-9]@[a-zA-Z]+"
     
                            + "[a-zA-Z0-9\\._-]*[a-zA-Z0-9]+\\.[a-zA-Z]{2,4}$";
     
    Pattern pattern = Pattern.compile(masque);
     
    Matcher controler = pattern.matcher(line2);
     
     
                    if(controler.matches() ){
                        arrayOfStrings.add(line2);
     
                    HashSet<String> h = new HashSet<String>(arrayOfStrings);
                    arrayOfStrings.clear();
                    arrayOfStrings.addAll(h);
                    }
     
            }
                while ((line = reader2.readLine()) != null) {
     
                    String masque = "^[a-zA-Z]+[a-zA-Z0-9\\._-]*[a-zA-Z0-9]@[a-zA-Z]+"
     
                            + "[a-zA-Z0-9\\._-]*[a-zA-Z0-9]+\\.[a-zA-Z]{2,4}$";
     
    Pattern pattern = Pattern.compile(masque);
     
    Matcher controler = pattern.matcher(line);
     
     
                    if(controler.matches() && !arrayOfStrings.contains(line) ){
     
                        out.write(line + "\n");
     
     
                    }
    biensur je n'oublie pas de fermer les flux en fin de traitement

  5. #5
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,



    Le code en lui-même n'est pas mauvais... mais comme il est exécuté un très grand nombre de fois (via les deux boucles) il faut faire attention à ce qu'on fait, et éviter les traitements et création d'objet inutile...





    Quelques exemples :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    String masque = "^[a-zA-Z]+[a-zA-Z0-9\\._-]*[a-zA-Z0-9]@[a-zA-Z]+"
    	+ "[a-zA-Z0-9\\._-]*[a-zA-Z0-9]+\\.[a-zA-Z]{2,4}$";
    Pattern pattern = Pattern.compile(masque);
    Tu défini le masque et crée le pattern au début de tes deux boucles, et à chaque itération. Or ce pattern ne change pas : il n'y a pas de raison de le recréer à chaque itération. Surtout que dans les regexp le plus coûteux vient de la création du Pattern justement.

    Initialises cela une seule et unique fois au début de ton code.






    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    if(controler.matches() ){
    	arrayOfStrings.add(line2);
     
    	HashSet<String> h = new HashSet<String>(arrayOfStrings);
    	arrayOfStrings.clear();
    	arrayOfStrings.addAll(h);
    }
    Ici si je comprend bien tu veux ajouter l'élément à la liste sans qu'il n'y ait de doublons. Donc à chaque fois tu crées un Set temporaire, tu vides la List et tu la re-remplie...

    Pourquoi ne pas utiliser directement un HashSet ? Ce serait plus simple et cela éviterai toutes ces manipulations. De plus l'appel de contains() sera lui aussi surement plus performant...





    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    out.write(line + "\n");
    Ici avec la concaténation tu crées une String temporaire. Ce n'est pas couteux en soit mais comme c'est fait un grand nombre de fois au bout du compte cela peut faire beaucoup.

    On peut éviter cela facilement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    out.write(line);
    out.write("\n");







    Citation Envoyé par infoinf Voir le message
    biensur je n'oublie pas de fermer les flux en fin de traitement
    Via des try/finally j'espère...


    a++

  6. #6
    Membre à l'essai
    Inscrit en
    Septembre 2010
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 12
    Points : 11
    Points
    11
    Par défaut
    j'ai fais les modifications que vous m'avez suggéré et le résultat est hallucinant j'ai fais 400000 ligne en 12 minutes alors qu'il traitait les 400000 lignes en 5h.

    je n'ai pas encore testé pour les 4 millions de ligne mais je pense que ça doit faire vers les 2h

    merci encore une fois pour votre aide

  7. #7
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    ben oui, en même temps faut avoir le reflexe de calculer un peut le temps de tes algorithme et t'aurais trouvé le problème tout de suite.
    Le new HashSet prend un temps O(n log n) et le nouveaux ArrayList prend un temps O(n), n étant sa taille, donc proportionnelle à la taille du fichier. Donc on arrive avec la boucle en un O(n²log n). donc si pour 400.000 lignes t'en arrive à 20 minutes, pour 10 fois plus de lignes t'en arrive à plus de 100fois plus, soit donc plus de 30 heures

    Avec l'algorithme utilisant directement le hashset tu passe à un temps moyen N log N, ce qui amène l'algo à monter beaucoup plus lentement en consommation de temps. Pour une multiplication par 10 de la taille, on est dans l'ordre d'une multiplication similaire du temps de calcul (donc passage de 20 minute à 3h)

Discussions similaires

  1. Lecture fichier port COM en java
    Par makia42 dans le forum Entrée/Sortie
    Réponses: 8
    Dernier message: 19/12/2013, 11h01
  2. [XL-2003] Ouverture d'un fichier très lente
    Par sinople dans le forum Excel
    Réponses: 3
    Dernier message: 05/11/2012, 17h17
  3. [WD-2003] Modifications de fichier très lentes en TSE
    Par carden752 dans le forum Word
    Réponses: 9
    Dernier message: 25/11/2011, 00h01
  4. [XL-2003] fichier très lent
    Par zangaloni dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 01/08/2011, 18h56
  5. Lecture de fichier binaire fortran avec java
    Par bigbrother737 dans le forum Langage
    Réponses: 1
    Dernier message: 11/05/2007, 10h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo