Optimisation du code

Résolu/Fermé
Charles-Henri - 6 nov. 2012 à 12:04
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 - 24 janv. 2013 à 17:04
Bonjour,
Voila j'ai codais un programme qui me permet de récupérer toutes les lignes correspondant à chaque navire dans un second fichier.
le programme marche niquel sauf que je trouve que ce ne le fait pas assez vite je pense donc avoir un problème d'optimisation notamment avec la fermeture du fichier qui je pense n'est pas au bon endroit.
Voici mon programme :


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;

public class Lecture_Fichier {

public static void main(String[] args) {
BufferedReader LecteurBufferise = null;
BufferedWriter EcrireBufferise = null;
File file = null;
String Chemin = "C:/***/***/***/***/Fichier1.txt";
String ligneDonnee;
boolean eof = false;

try {
LecteurBufferise = new BufferedReader(new FileReader(Chemin));
while (eof != true)
{
/*System.out.println("-> Lecture");*/
ligneDonnee = LecteurBufferise.readLine();
if (ligneDonnee != null)
{
/*System.out.println("--> Split");*/
String[] mesMots = ligneDonnee.split(";");

file = new File("C:/***/***/***/***/" + mesMots[0] + ".txt");
/*System.out.println("---> Création");*/
if(!file.exists())
{
file.createNewFile();
}
/*System.out.println("Debut de l'écriture");*/
EcrireBufferise = new BufferedWriter(new FileWriter(new File("C:/***/***/***/***/" + mesMots[0] + ".txt"), true));
/*System.out.println("----> Ecriture");*/
EcrireBufferise.write(ligneDonnee);
/*System.out.println("-----> Ligne écrite");*/
EcrireBufferise.write(";");
EcrireBufferise.write("\r\n");
EcrireBufferise.flush();
EcrireBufferise.close(); <-----Bien placé ou non ???
/*System.out.println("------> Fin Ecriture");*/
}
else
{
eof = true;
}
}
} catch (FileNotFoundException ex) {
System.out.println("Fichier Non Trouvé !!");
} catch (IOException ex) {
System.out.println("Problème de lecture du fichier !!");
} finally {
try {
LecteurBufferise.close();
} catch (IOException ex1) {
System.out.println("Problème de fermeture du fichier !!");
}
}
}
}

Est ce que le "EcrireBufferise.close();" est bien placé puisque c'est long à faire le traitement du coup si vous voyez quelque chose qui cloche merci de me le dire :)
A voir également:

8 réponses

Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
6 nov. 2012 à 12:32
Tu écris un nouveau fichier par ligne lue, je ne vois pas comment optimiser.
Seul point que je trouve étrange, c'est :
EcrireBufferise = new BufferedWriter(new FileWriter(new File("C:/***/***/***/***/" + mesMots[0] + ".txt"), true));
J'aurai simplement mis EcrireBufferise = new BufferedWriter(new FileWriter(file, true));
sinon, l'utilisation de file est un peu limiter.
0
Charles-Henri
6 nov. 2012 à 13:24
Oui cela revient au même mais les performances sont les mêmes....
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
6 nov. 2012 à 15:32
Oui, ça doit être pareil car ce n'est pas là que le temps doit être majoritairement perdu.
Mais dans ton cas, tu crées deux fois un objet de type File, ça doit bien prendre du temps.

Essai de virer flush() et de ne laisser que close().
En toute théorie, close() fait un flush avant de fermer réellement un fichier. La différence qu'il peu y avoir c'est que flush est bloquant mais pas forcément close(). L'idée c'est que l'OS mette en tâche de fond l'écriture et la fermeture des fichiers, pendant que ton programme continue à s'exécuter. Du coup ton programme n'attend pas sans rien faire -> optimisation.
0
Charles-Henri
6 nov. 2012 à 15:35
Ok merci char snipeur je test ca et je te tiens au courant
0
Charles-Henri
7 nov. 2012 à 09:07
ça ne change rien en enlevant le flush. Je commence à désespérer sérieusement là.
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
7 nov. 2012 à 09:55
Combien de temps il prend ton programme ?
Il est difficile de t'aider, car nous n'avons pas l'intégralité de ton problème.
Par exemple, une fonction qui peut prendre du temps c'est split(';'). Si la ligne est très très longue, ça peu prendre beaucoup de temps. Surtout que tu ne t'en sert pas, pour récupérer le premier mot, un truc dans le genre de first(';') (je ne sais pas si la fonction existe, mais c'est l'idée) suffirait.
Pour faire un vrai optimisation une fois que tu as éliminé les causes algorithmique, c'est de faire un profilage, de voir où tu perds le plus de temps pour cibler tes efforts d'optimisation.

Autre point, est-ce que le try ne prendrait pas du temps ?
0
Charles-Henri
7 nov. 2012 à 10:08
Cela dépend des fichiers ! mais un fichier de 2G prend plusieurs jours ^^
Mais ligne ne sont pas longues mais le problème c'est que j'en ai plus de 3 millions dans certains fichiers..du coup cela prends énormément de temps.
Ce qui est long d'après ce que j'ai constaté c'est l'écriture dans le fichier créé puisque si tu veux à la base j'ai un fichier avec toutes les données de tous les bateaux confondues et moi dans mon programme, je veux qu'il créé un fichier pour chaque bateau identifié dans le fichier et qu'il récupère chaque ligne qui correspond à ce bateau.
Par exemple si j'ai 1500 bateau dans le fichier, je veux qu'il me créé 1500 fichiers.
Ensuite, si pour un bateau j'ai 2320 lignes ben je veux que ces 2320 lignes apparaissent dans le fichier créé pour ce bateau. Et je pense que c'est cette partie qui prend du temps ! C'est l'écriture des infos dans chaque fichier puisque la création de chaque fichier n'est potentiellement pas long.
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
7 nov. 2012 à 10:34
Un truc m'avait échappé. J'avais compris que tu créai un fichier pour chaque ligne de ton fichier source. En fait, au début de chaque ligne, il y a le nom d'un bateau, et le bateu est présent sur plusieurs lignes. Je pense qu'il faut revoir ton algorithme.
Deux cas de figure :
1. Les bateaux identiques sont à la suite dans le fichier source. Tu crées une fonction d'écriture et une variable d'accumulation. Comme ça tu ne fait qu'une opération d'ouverture écriture fermeture.

2. Les bateaux sont éparpillé dans le fichier source. Là c'est plus compliqué. Je ferai un tableau de buffer pour chaque bateau, en C++ un std::map serait idéal (voir l'équivalent java). et à chaque ligne tu écris, comme ça tu ne fait qu'une opération d'ouverture fermeture pour chaque bateau, sans flush, on peu espérer que les buffer se débrouilleront pour optimiser l'écriture (normalement, ils sont là pour ça). Puis fermer tout les buffer à la fin

Sur les PC actuel, ce qui est le plus pénalisant en temps c'est l'écriture sur les disques.
0
Charles-Henri
7 nov. 2012 à 10:38
Oui voila tu as bien compris ce que je voulais. J'ai un bateau en début de chaque ligne et à partir de là si un bateau est différent d'une ligne à l'autre, un fichier est créé avec le nom du nouveau bateau et ainsi de suite!
Et c'est la première solution la bonne, les bateaux sont à la suite dans le fichier mais je ne vois pas trop comment faire d'après ce que tu dis.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
7 nov. 2012 à 10:56
string ACCU;
string nomcourant,nombateau="";
while(eof)
    ...
    nomcourant=ligneDonne.split(';)[0];
    if(nomcourant==nombateau)
         ACCU+=ligneDonne+";\r\n";
    else
         ecrifichier(nombateau,ACCU);
         ACCU=ligneDonne+";\r\n";
         nombateau=nomcourant;
    fin if
    ...
finwhile 
...

Voilà comment je vois le truc en pseudo code. ecrifichier est une fonction qui va ouvrir ton fichier, écrire ACCU dedans et le fermer.
0
Charles-Henri
7 nov. 2012 à 11:43
Tu veux pas essayer de l'adapter à mon code parce que la, je ne vois pas comment tourner la chose depuis taleur je me casse les dents dedans !
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
7 nov. 2012 à 12:30
Je suis mauvais en Java, donc non.
Met ce que tu as fais, je corrigerai.
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
7 nov. 2012 à 12:39
Je reprends ton code initial pour en faire un code Java propre :

Remarque : j'ai enlevé le split(";") qui est une opération très lourde alors que tu ne te sers que de la première case.

public static void main(String[] args) throws IOException
{     
    String dossier = "C:/***/***/***/***/";
    Scanner sc = new Scanner(new File(dossier,"Fichier1.txt"));
        
    while (sc.hasNextLine()) 
    { 
        String ligne = sc.nextLine();        
        String debut = ligne.substring(0, ligne.indexOf(";"));
        FileWriter writer = new FileWriter(new File(dossier,debut+".txt"),true);
        writer.write(ligne+";"+System.lineSeparator());
        writer.close();
    }
    
    sc.close();
}

Je vais essayer de relire toute la discussion, j'ai vu passer une histoire de map, mais je n'ai pas trop compris l'histoire des bateaux...
0
Charles-Henri
7 nov. 2012 à 12:54
Salut KX,
Alors enfet, j'ai un bateau en début de chaque ligne et à partir de là si un bateau est différent d'une ligne à l'autre, un fichier est créé avec le nom du nouveau bateau et ainsi de suite! Par exemple si j'ai 1500 bateau dans le fichier, je veux qu'il me créé 1500 fichiers.
Ensuite, si pour un bateau j'ai 2320 lignes ben je veux que ces 2320 lignes apparaissent dans le fichier créé pour ce bateau.
Donc voila, je suis entrain de tester ta solution et je te tiens au courant !
Merci beaucoup en tout acs ^^
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
Modifié par KX le 7/11/2012 à 13:05
"Ma solution" ce n'est rien d'autre que ton code initial réécrit proprement (au split prêt).
Pour prendre en compte les spécificités de ton fichier, à savoir que toutes les lignes d'un même bateau se suivent, il faut utiliser l'accumulateur dont parlait Char Snipeur (j'ai utilisé un StringBuilder)

public static void main(String[] args) throws IOException
{     
    String dossier = "C:/***/***/***/***/";
    Scanner sc = new Scanner(new File(dossier,"Fichier1.txt"));
    
    String bateauAvant = null;
    StringBuilder sb = null;
    
    while (sc.hasNextLine()) 
    {
        String ligne = sc.nextLine();
        String bateau = ligne.substring(0, ligne.indexOf(";"));
        
        if (!bateau.equals(bateauAvant))
        {
            if (bateauAvant!=null)
            {
                FileWriter writer = new FileWriter(new File(dossier,bateauAvant+".txt"));
                writer.write(sb.toString());
                writer.close();
            }
            
            sb = new StringBuilder();
            bateauAvant = bateau;
        }
        
        sb.append(ligne+";"+System.lineSeparator());
    }
    
    if (sb.length()!=0)
    {
        FileWriter writer = new FileWriter(new File(dossier,bateauAvant+".txt"));
        writer.write(sb.toString());
        writer.close();
    }
    
    sc.close();
}
0
Charles-Henri
7 nov. 2012 à 13:19
Niquel merci beuacoup KX !!
Je vais tester ca et je te tiens au courant !
Encore merci
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
7 nov. 2012 à 13:21
Testes déjà sur un petit fichier, y a peut-être des bugs...
0
Charles-Henri
7 nov. 2012 à 13:45
C'est ENORME ^^ ca va trop vite mtn !
Du coup j'utilise plus de tableau mtn c'est bien ça?
0
Charles-Henri
7 nov. 2012 à 13:49
J'ai juste mon dernier fichier qui est créé dans le chemin indiqué dans la variable 'dossier' autrement c'est très très fluide !!!!
Vraiment merci
0