Optimisation du code
Résolu
Charles-Henri
-
KX Messages postés 16761 Date d'inscription Statut Modérateur Dernière intervention -
KX Messages postés 16761 Date d'inscription Statut Modérateur Dernière intervention -
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 :)
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:
- Optimisation du code
- Code ascii - Guide
- Optimisation pc - Accueil - Utilitaires
- Code puk bloqué - Guide
- Code activation windows 10 - Guide
- Comment déverrouiller un téléphone quand on a oublié le code - Guide
8 réponses
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.
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.
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.
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.
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 ?
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 ?
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.
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.
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.
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.
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.
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.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre questionstring 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.
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 !
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.
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...
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...
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 ^^
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 ^^
"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)
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(); }