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

Java Discussion :

Problème Scanner sur Gros fichier


Sujet :

Java

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 116
    Points : 53
    Points
    53
    Par défaut Problème Scanner sur Gros fichier
    Bonjour à tous,
    Voici mon petit problème actuel :
    - j'ai un gros fichier MSF (fichier des messages de thunderbird) de 300 Mo
    - j'essaye de le séparer en plusieurs petits fichiers selon un délimiteur
    - j'utilise donc la classe Scanner en utilisant un délimiteur : c'est franchement exactement ce qu'il me faut, et ça marche bien jusqu'à un bon vieux Java Heap Space ! Du coup, je ne sais pas exactement comment marche cette classe : le scanner ne se vide-t-il pas après chaque occurrence trouvée ?

    Voici le code

    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
     
    try {
          Scanner scanner = null;
           try {
                 scanner = new Scanner(new BufferedReader(
    								new FileReader(file)));
    	     scanner.useDelimiter(Pattern.compile("From "));
    	     int j = 0;
    	     String sMessage = null;
    	     while (scanner.hasNext()) {
    			sMessage = scanner.next();
    			if (sMessage.length() > 0) {
    			     System.out.println("MESSAGE NUMERO " + j);
    			     System.out.println(sMessage.substring(0, 50));
    		                 System.out									.println("#################################");
    //			      }
    			  j++;
    	       }
    	} finally {
    		if (scanner != null)
    		     scanner.close();
    }
    } catch (IOException e) {
    	e.printStackTrace();
    }
    Pour tester, on peut tester sur n'importe quelle boite aux lettres Thunderbird : pas le fichier MSF, mais le pendant sans extension.

    Ce que j'ai essayé jusqu'à présent :
    - BufferedReader + FileReader : lecture ligne à ligne beaucoup trop lente sur un fichier de 300 Mo
    - JMork : les fichiers MSF étant des fichiers mork, j'ai essayé cette api mais ça ne donne rien
    - Scanner avec findWithinHorizon + un Horizon à 0 : ça revient au même qu'un bufferedreader --> très lent

    Voilà, j'espère que vous pourrez me dépanner, car je n'ai encore trouver aucune solution satisfaisante !
    Merci !

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 559
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 559
    Points : 21 621
    Points
    21 621
    Par défaut
    Citation Envoyé par maccormick Voir le message
    Du coup, je ne sais pas exactement comment marche cette classe : le scanner ne se vide-t-il pas après chaque occurrence trouvée ?
    La doc ne le dit pas, mais on peut raisonnablement le penser, si.

    Maintenant, il est possible qu'il y ait des occurrences vraiment énormes et qu'il n'arrive pas à les stocker en mémoire. Après tout il doit d'abord les stocker dans un buffer, puis ensuite dupliquer le buffer dans une String.
    Normalement avec un fichier de 300Mo on devrait rester un peu en-dessous des limites de mémoire classiques, mais avec des occurrences très grosses ça flirte bien avec ces mêmes limites.

    Citation Envoyé par maccormick Voir le message
    Ce que j'ai essayé jusqu'à présent :
    - BufferedReader + FileReader : lecture ligne à ligne beaucoup trop lente sur un fichier de 300 Mo
    - JMork : les fichiers MSF étant des fichiers mork, j'ai essayé cette api mais ça ne donne rien
    - Scanner avec findWithinHorizon + un Horizon à 0 : ça revient au même qu'un bufferedreader --> très lent
    Ça ne sert à rien de filer un BufferedReader à un Scanner : il a ses propres buffers. Le FileReader était suffisant. ... Mais bon c'est pas le problème.

    Un horizon à zéro n'avait clairement aucune chance de résoudre des problèmes d'occupation mémoire.

    Tu pourrais essayer de lire juste un FileReader au lieu d'un BufferedReader. La bufferisation c'est toi qui te la tapes, et la détection des "From " aussi (et même gérer l'overlap d'un buffer à l'autre.)
    Cela t'évitera de stocker en mémoire tout ce qui sépare deux Froms, et tu pourras juste garder les 50 premiers caractères comme dans ton exemple.
    C'est assez chiant à programmer mais ça permet de respecter les contraintes.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 394
    Points : 639
    Points
    639
    Par défaut
    Bonsoir,

    Pour le scanner je n'ai pas d'explication, je ne vois rien qui devrait provoquer une fuite mémoire.

    As-tu essayé de changer la taille du BufferedReader qui est assez basse de base (8ko) ?

    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
    BufferedReader bufferedReader = null;
    		try {
    			bufferedReader = new BufferedReader(new FileReader(file), 10485760); // buffer de 10mo
    			String line;
    			while ((line = bufferedReader.readLine()) != null) {
    				// traiter la ligne ici
    			}
    		} finally {
    			if (bufferedReader != null) {
    				try {
    					bufferedReader.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    Pas de raison que ça soit spécialement lent avec un BufferedReader bien réglé, le but du bufferreader étant justement de minimiser les accès disques tout en ne consommant pas trop de mémoire.


    System.out ça doit ralentir aussi ton programme (mais je ne sais pas trop dans quelle mesure)... Tu voudrais peut-être utiliser un BufferedWriter pour minimiser les accès disque en écriture ?

    Romain.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 116
    Points : 53
    Points
    53
    Par défaut
    Merci à tous les deux, ça marche nickel en laissant le scanner gérer seul son "file", en tout cas pour un fichier de 300 Mo !
    je mets le code, et je mets la discussion en résolu !

    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
     
     
    try {
    					// FileReader reader = new FileReader(file);
    					Scanner scanner = null;
    					try {
    						scanner = new Scanner(file);
    						scanner.useDelimiter(Pattern.compile("From\\s"));
    						int j = 0;
    						String sMessage = null;
    						while (scanner.hasNext()) {
    							sMessage = scanner.next();
    							if (sMessage.length() > 0) {
    								System.out.println("MESSAGE NUMERO " + j);
    								System.out.println(sMessage.substring(0, 50));
    								System.out
    										.println("#################################");
    							}
    							j++;
    						}
    					} finally {
    						if (scanner != null)
    							scanner.close();
    					}
    				} catch (IOException e) {
    					e.printStackTrace();
    				}

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème 'Scanner' , lire un fichier .txt
    Par eXystenZ dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 17/03/2009, 20h32
  2. Réponses: 5
    Dernier message: 09/01/2008, 20h30
  3. Opération sur (gros) fichier
    Par sloshy dans le forum C
    Réponses: 8
    Dernier message: 24/10/2007, 19h24
  4. problème écriture sur un fichier
    Par drinkmilk dans le forum MFC
    Réponses: 4
    Dernier message: 24/06/2007, 00h08
  5. [Upload] Problème upload de gros fichiers avec Firefox
    Par the rootsm@n dans le forum Langage
    Réponses: 12
    Dernier message: 19/02/2006, 20h43

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