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 :

[Débutant] objet : contenu et référence vu pas un noob


Sujet :

Langage Java

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 38
    Par défaut [Débutant] objet : contenu et référence vu pas un noob
    Hello,

    J'essaie de ma mettre à Java, mais c'est pas si simple ...

    Je fais un programme qui va récupérer des informations dans un fichier texte et les met ensuite dans un fichier texte séparé par ";".

    J'ai donc une classe FicSortie qui implémente un objet à partir du répertoire et du nom de ficher. Jusque là ça va . Maintenant j'ai plusieurs méthodes, et c'est là je pense que je fais pas ce qu'il faut ...

    Pour résumer, mon fichier de test initial ne comprenait que 1100 lignes, donc le traitement était assez rapide. J'ai voulu le tester sur un fichier de 34000 lignes et là même après un café ça avait toujours pas finit !! Un script plus complexe en perl s'exécute en quelques secondes sur le même fichier

    Bref, j'ai construit ma classe ainsi:
    - constructeur : à partir du répertoire et du nom de fichier
    - méthode contenu : lit le fichier ligne à ligne et renvoie un String où chaque ligne est séparée par un ";"
    - méthode nbAnalyses : split le résultat de contenu() par ";", et compte le nombre d'occurences d'une chaine de texte ("IDENTIFICATION"), renvoie un Integer
    - méthode listeAnalyses : split le résultat de contenu() par ";", et récupère les identifiants concernés, renvoie un Integer[] contenant les identifiants (qui sont donc des entiers)
    - contenuAnalyse(identifiant) : split le résultat de contenu() par ";", recherche la partie concernant l'identifiant passé en argument, et renvoie un String[] avec les infos nécessaires

    Au début à chaque appel de .contenu() il relisait le fichier texte, plutôt long , donc j'ai ajouté dans ma classe un booléen qui sert à savoir si le contenu a déjà été récupéré, et si c'est le cas alors contenu() le renvoie mais sans relire le fichier (un String le stocke dans la classe).

    Néanmoins j'ai l'impression que j'emmêle les pinceaux dans la manipulation des objets, je pense stocker le résultat de .contenu().split(";") dans un String[], hors à chaque fois que j'utilise ledit String[] il fait appel à ma méthode contenu(), est-ce normal ?

    Mon programme principal :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public static void main(String[] args) {	
     
    	FicSortie fichier = new FicSortie("C:\\MONCHEMIN\\","fichier.txt");
     
    	System.out.println("Nombre d'analyses : "+fichier.nbAnalyses());
    	System.out.println("Analyses n° 3 : "+fichier.listeAnalyses()[2]);
     
    	}
    Et ma classe FicSortie :

    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    import java.io.BufferedReader;
    import java.io.FileReader;
     
    public class FicSortie {
     
    	// Variables d'instance
    	private String monChemin;
    	private String monFichier;
     
    	// Variables globales
    	private Boolean dejaFait; // pour savoir si le fichier a déjà été récupéré
    	private String contenuFichier; // contenu du fichier si déjà récupéré
     
    	// Constructeur	
    	public FicSortie(String chemin, String fichier) {
    		monChemin = chemin;
    		monFichier = fichier;
    		dejaFait = false;
    		contenuFichier = null;
    	}
     
     
    // les méthodes
     
    // renvoie le nombre d'analyses
    	public Integer nbAnalyses (){
    		Integer comptage=0; // pour compter le nombre d'analyses, sert de retour
    		String[] champsContenu=null; // tableau contenant les lignes de .contenu() splittées par ;
     
    		champsContenu=contenu().split(";"); 
     
    		for (int cpt = 0; cpt < champsContenu.length ; cpt++){
    			if (champsContenu[cpt].equals("IDENTIFICATION")){
    				comptage++;
    			} // fin du if
    		} // fin de la boucle for
     
    		return comptage;
    	}
     
    // renvoie un Integer[] contenant les numéros d'analyses
            public Integer[] listeAnalyses () {
    		String[] champsContenu=contenu().split(";"); // tableau contenant les lignes de .contenu() splittées par ;
    		String listeConcateneAnalyses = null;
     
    		Integer[] listeRetourAnalyses = new Integer[nbAnalyses()];
    		int cpt2 = 0 ; // intialisation du compteur pour le tableau d'entiers listeRetourAnalyses
     
    		for (int cpt = 0; cpt < champsContenu.length ; cpt++){
    			if (champsContenu[cpt].equals("IDENTIFICATION")){
    				if (listeConcateneAnalyses == null){
    					listeRetourAnalyses[cpt2] = Integer.valueOf(champsContenu[cpt+1]);
    					cpt2++;
    					listeConcateneAnalyses = champsContenu[cpt+1];
    				} // fin du if
    				else {
    					listeRetourAnalyses[cpt2] = Integer.valueOf(champsContenu[cpt+1]);
    					cpt2++;
    					listeConcateneAnalyses = listeConcateneAnalyses+";"+champsContenu[cpt+1];
    				} // fin du else
    			} // fin du if
    		} // fin de la boucle for
     
    		champsContenu = listeConcateneAnalyses.split(";");
     
    		return listeRetourAnalyses;
    	}
     
    // renvoie le contenu du fichier
    	private String contenu (){
    		BufferedReader lecture=null;
    		if (dejaFait) {
    			// TEST
    			System.out.println("Fichier : déjà ouvert");
    			return contenuFichier;
    		}
    		else {
    			try{
    				FileReader fichierAlire = new FileReader(monChemin + monFichier);
    				// TEST
    				System.out.println("1ère ouverture du fichier");
    				lecture = new BufferedReader(fichierAlire);
    			} catch (Exception e){
    				Erreur(e,1);
    			}
    		}
     
    		String ligne=null; // pour stocker le contenu de chaque ligne lue
    		String ligneConcatene=null; // pour TEST
     
    		try{
    			while((ligne=lecture.readLine())!=null){
    				if (ligneConcatene == null){
    					ligneConcatene = ligne;
    				} // fin du if
    				else {
    					ligneConcatene = ligneConcatene+";"+ligne;
    				} // fin du else
     
    			} // fin du while
    		} catch (Exception e){
    			Erreur(e,2);
    		} // fin gestion erreur sur ouverture
     
    		// fermeture fichier
    		try{
    		lecture.close();
    		} catch (Exception e){
    		Erreur(e,3);
    		} // fin gestion d'erreur sur fermeture
     
    		//System.out.println("Fichier "+fichier+" fermé");
    		contenuFichier = ligneConcatene; // on stocke dans la variable globale le contenu du fichier
    		dejaFait = true; // on met true pour dire que c'est déjà fait
    		return ligneConcatene;
    	}
     
    // Gestion des erreurs
    	private static void Erreur(Exception e, int code){
    		System.err.println("Erreur : "+e);
    		System.exit(code);
    		}
     
    	public static void main(String[] args) {
    			} 
     
    }
    Pour information ça me renvoie :
    Ceci est un test
    On va tester la lecture du fichier de sortie
    On vient d'instancier l'objet FicSortie
    1ère ouverture du fichier
    Nombre d'analyses : 9
    Fichier : déjà ouvert
    Fichier : déjà ouvert
    Analyse numéro 3 : 7400
    C'EST FINI !!
    Donc, normalement dans ma méthode listeAnalyses(), la ligne String[] champsContenu=contenu().split(";"); fait appel à contenu() et stocke bien des éléments String dans le String[] champsContenu, donc les futures opérations sur champsContenu ne feront pas appel à contenu(), n'est-ce pas ?

    Est-ce que je devrais pour contenu() plutôt que renvoyer une chaine texte séparée par des ";" renvoyer un String[] ?

    Existe-il une méthode plus rapide pour lire un fichier texte de 34000 lignes ??

    Usti

  2. #2
    Expert confirmé
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Par défaut
    Ton problème est ici :

    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
    String ligne=null; // pour stocker le contenu de chaque ligne lue
    		String ligneConcatene=null; // pour TEST
     
    		try{
    			while((ligne=lecture.readLine())!=null){
    				if (ligneConcatene == null){
    					ligneConcatene = ligne;
    				} // fin du if
    				else {
    					ligneConcatene = ligneConcatene+";"+ligne;
    				} // fin du else
     
    			} // fin du while
    		} catch (Exception e){
    			Erreur(e,2);
    		} // fin gestion erreur sur ouverture
    Il vient de la manière de concaténer des String dans une boucle. En fait, cette ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ligneConcatene = ligneConcatene+";"+ligne;
    est équivalente à celle-ci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ligneConcatene = new StringBuffer(ligneConcatene).append(";").append(ligne).toString();
    Donc, tu as une création d'objet à chaque ligne et il se trouve que la création d'objet est très lente. Donc il faut éviter d'employer la concaténation des String dans une boucle.

    Pour résoudre ton problème, il faut employer directement un StringBuffer et sa méthode append :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    String ligne=null; // pour stocker le contenu de chaque ligne lue
    		StringBuffer ligneConcatene=null; // pour TEST
     
    		try{
    			while((ligne=lecture.readLine())!=null){
    				ligneConcatene.append(";").append(ligne);
    			} // fin du while
    		} catch (Exception e){
    			Erreur(e,2);
    		} // fin gestion erreur sur ouverture
    et tu utilises toString pour récupérer le String :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return ligneConcatene.toString();
    Bon, ca c'était pour la petite histoire, mais en fait, ton truc, c'est un peu bête, car tu mets tout ensemble puis tu redécoupes, donc, je te conseillerais plutôt d'utiliser un tableau de String comme tu l'as dit

  3. #3
    in
    in est déconnecté
    Membre Expert Avatar de in
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    1 612
    Détails du profil
    Informations personnelles :
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 612
    Par défaut
    Citation Envoyé par ustilago
    méthode contenu : lit le fichier ligne à ligne et renvoie un String où chaque ligne est séparée par un ";"
    c'est ça qui est un peu bourrin non ?

    Tu devrais, comme le dis Witchounet, utiliser un tableau de String (ou une ArrayList de String)

    Au lieu de créer une mégagrosse chaine de caractères que tu vas splitter pour récupérer les lignes que tu as déjà lues, tu devrais direct stocker tes lignes dans une structure.

    par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ArrayList<String> mesLignes = new ArrayList<String>();
    while(ligne lue)
        mesLignes.add(la ligne lue)
    Comme ça déjà, tu n'es plus obliger de splitter cette chaine.
    Tu peux ensuite transformer cette liste en un tableau de string. et là tu continues le traitement comme avant ...

    En espérant ne pas t'embrouiller ...

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 38
    Par défaut
    Oulala, effectivement, l'idée du StringBuffer est bien trouvée !! Ca s'exécute d'un coup nettement plus rapidement.

    C'est un peu dur au début de tout assimiler, je me souviens d'avoir vu cette méthode de traitement des chaînes de caractères, mais je n'avais pas compris à l'époque son intérêt par rapport à une bête concaténation comme en perl .

    Je vais effectivement modifier cette méthode pour qu'elle renvoie directement un tableau String[] vu que c'est ce que je fais en premier quand je l'appelle .

    Merci de votre aide, je vous solliciterai sûrement à nouveau

    Usti

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 01/11/2008, 20h19
  2. Réponses: 3
    Dernier message: 04/04/2008, 18h02
  3. Réponses: 2
    Dernier message: 30/12/2006, 13h34
  4. Réponses: 1
    Dernier message: 18/05/2006, 14h09
  5. [Débutant] Objet découpé et perspective
    Par Pedro dans le forum DirectX
    Réponses: 20
    Dernier message: 25/01/2005, 15h21

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