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

Entrée/Sortie Java Discussion :

Dédoublonnage de fichiers volumineux


Sujet :

Entrée/Sortie Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Octobre 2011
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 3
    Par défaut Dédoublonnage de fichiers volumineux
    Bonjour tout le monde,
    pour commencer je tiens à dire que je ne suis pas un crack en java, donc je vous demande de l'aide^^.
    Mon problème j'ai deux fichiers en entrée chacun de ces fichiers peut aller jusqu'à 30 Mo (20000 lignes) et je dois créer un nouveau fichier avec toutes les lignes de ces deux fichiers moins les doublons.
    Voilà ce que j'ai fait et même si c'est fonctionnel avec des petits fichiers avec 20000 lignes je vais y passer (si mes calculs sont bons) 155h , donc je me tourne vers vous pour trouver un algo plus efficace (qui n'ai pas un temps qui augmente au carré), sachant qu'il ne faut pas que je mettes trop de choses en mémoire et qu'il faudrait que ça me prenne le moins de temps possible (<24h).
    Les lignes ne sont pas ordonnés et je prends que les caractères 2 à 11 d'une ligne pour comparer.

    Merci d'avance à ceux qui prendront le temps de me répondre.

    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
     
    		Calendar calendar = new GregorianCalendar();
    		int start = calendar.get(Calendar.MINUTE);
     
    		// Ecriture du fichier Fichier1 et releve des doublons
    		try {
     
    			FileReader fileReaderFichier1 = new FileReader(filePathFichier1);
    			// voir le LineNumberReader extends BufferedReader
    			BufferedReader bufferedReaderFichier1 = new BufferedReader(
    					fileReaderFichier1);
     
     
    			ArrayList<Integer> tableauDoublons = new ArrayList<Integer>();
    			String ligneFichier1;
    			String ligneFichier2;
    			FileWriter fileMergeWriter = new FileWriter(filePathMerge, true);
     
    			while ((ligneFichier1 = bufferedReaderFichier1.readLine()) != null) {
    				Integer i = 0;
    				FileReader fileReaderFichier2 = new FileReader(filePathFichier2);
    				BufferedReader bufferedReaderFichier2 = new BufferedReader(
    						fileReaderFichier2, 71100);
     
    				while ((ligneFichier2 = bufferedReaderFichier2.readLine()) != null) {
    					i++;
    					if (ligneFichier1.substring(2, 11).equals(ligneFichier2.substring(2,11))) {
    						tableauDoublons.add(i);
    					}
    				}
    				fileMergeWriter.write(ligneFichier1 + "\n");
    				fileMergeWriter.flush();
    			}
    			bufferedReaderFichier1.close();
     
    			// Ecriture du fichier Fichier2 sans doublon
     
    			Integer numLigneFichier2 = 0;
    			FileReader fileReaderFichier2 = new FileReader(filePathFichier2);
    			BufferedReader bufferedReaderFichier2 = new BufferedReader(
    					fileReaderFichier2, 71100);
     
    			while ((ligneFichier2 = bufferedReaderFichier2.readLine()) != null) {
    				numLigneFichier2++;
    				if (!tableauDoublons.contains(numLigneFichier2)) {
    					fileMergeWriter.write(ligneFichier2 + "\n");
    					fileMergeWriter.flush();
    				}
    			}
    			fileMergeWriter.close();
    			bufferedReaderFichier2.close();
    			int end=calendar.get(Calendar.MINUTE);
    			System.out.println("Temps d'execution : " + (end - start));
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}

  2. #2
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Salut,


    Ce serait peut-être plus gourmand en mémoire, mais ce serait nettement plus performant de charger toutes les lignes dans un Set<String>, puis d'écrire ce dernier dans le fichier résultat...


    C'est quoi ta limite d'utilisation de la mémoire ???

    a++

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Octobre 2011
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 3
    Par défaut
    Merci 'avoir répondu aussi vite, mais j'ai trouvé la solution grâce au forum en fouillant bien et en mixant les différents pistes que j'ai trouvé. Je poste au cas où ça intéresse quelqu'un. En gros, je lis une ligne dans le premier fichier j'extrais l'identifiant (qui est la condition de dédoublonnage) dans une HashSet, je l'écris dans le fichier de sortie puis je boucle et quand je passe sur le second fichier je cherche l'éxistence de l'id par ligne dans la collection si il n’existe pas j'écris.
    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
     
    HashSet<String> collectionIdentifiant=new HashSet<String>();
     
    		long time = System.currentTimeMillis();
     
    		try {
    			BufferedReader buffFichier1 = new BufferedReader(new FileReader(
    					filePathFichier1));
    			BufferedReader buffFichier2 = new BufferedReader(new FileReader(
    					filePathFichier2));
    			FileWriter fileMergeWriter = new FileWriter(filePathMerge, true);
     
    			try {
    				String ligneFichier1;
     
    				while ((ligneFichier1 = buffFichier1.readLine()) != null) {
    					fileMergeWriter.write(ligneFichier1 + "\n");
    					collectionIdentifiant.add(ligneFichier1.substring(2, 11));
    				}
    			} finally {
    				buffFichier1.close();
    				fileMergeWriter.flush();
    			}
     
    			try {
    				String ligneFichier2;
    				String noRef2=null;
    				while ((ligneFichier2 = buffFichier2.readLine()) != null) {
    					noRef2=ligneFichier2.substring(2, 11);
    					if(!collectionIdentifiant.contains(noRef2))
    						fileMergeWriter.write(ligneFichier2 + "\n");
    				}
    			} finally {
    				buffFichier2.close();
    				fileMergeWriter.flush();
    				fileMergeWriter.close();
    			}
    		} catch (IOException ioe) {
    			System.out.println("Erreur --" + ioe.toString());
    		}
     
    		System.out.println("Temps d'exécution: " + (System.currentTimeMillis() - time));
    	}
    Je marque le sujet comme étant résolu !! (j'en suis assez fière mais c'est grâce à vous, merci)

  4. #4
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Quelques remarques :

    • Tu devrais avoir un try/finally par ressource, que tu ouvres juste après la création de la ressource. Sinon tu ne peux pas garantir que tout soit correctement fermer. Dans ton code en cas d'exception lors de la lecture du fichier 1, les deux autres fichiers ne sont pas fermés...
    • De même chaque bloc finally ne doit comporter qu'un seul et unique appel à close()...
    • Enfin attention avec le + "\n". Déjà cela crée un chaine temporaire inutilement (il faut mieux faire 2 appels à write()), mais le séparateur de ligne varie selon le système hôte. Il serait peut-être préférable d'utiliser System.getProperty("line.separator")
    • Enfin pour lire un fichier texte il peut être souhaitable de préciser l'encodage... sous peine de mauvaise surprise !
    • Enfin la gestion des exceptions est... "basique" !
      C'est normal que tu te contente d'afficher un message ? Ne devrait-on pas arrêter l'application ???



    Bref ton code peut ressembler à ceci :
    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
    try {
    	HashSet<String> collectionIdentifiant = new HashSet<String>();
    	String endl = System.getProperty("line.separator");
    	FileWriter fileMergeWriter = new FileWriter(filePathMerge, true);
    	try {
    		BufferedReader buffFichier1 = new BufferedReader(new FileReader(filePathFichier1));
    		try {
    			String line;
    			while ((line = buffFichier1.readLine()) != null) {
    				fileMergeWriter.append(line).append(endl);
    				collectionIdentifiant.add(line.substring(2, 11));
    			}
    		} finally {
    			buffFichier1.close();
    		}
     
    		BufferedReader buffFichier2 = new BufferedReader(new FileReader(filePathFichier2));
    		try {
    			String line;
    			while ((line = buffFichier2.readLine()) != null) {
     
    				String ref = line.substring(2, 11);
    				if (!collectionIdentifiant.contains(ref))
    					fileMergeWriter.append(line).append(endl);
    			}
    		} finally {
    			buffFichier2.close();
    		}
     
    		fileMergeWriter.flush();
     
    	} finally {
    		fileMergeWriter.close();
    	}
    } catch (IOException ioe) {
    	// ce serait peut-être mieux de planter le programme. Non ?
    	throw new RuntimeException(ioe);
    }

    A noter que Java 7 et son try-with-ressource permet de simplifier cela en gérant automatiquement (et proprement) les ressources :
    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 {
    	HashSet<String> collectionIdentifiant = new HashSet<String>();
    	String endl = System.getProperty("line.separator");
    	try ( FileWriter fileMergeWriter = new FileWriter(filePathMerge, true);
    	  BufferedReader buffFichier1 = new BufferedReader(new FileReader(filePathFichier1));
    	  BufferedReader buffFichier2 = new BufferedReader(new FileReader(filePathFichier2)) ) {
     
    		String line;
    		while ((line = buffFichier1.readLine()) != null) {
    			fileMergeWriter.append(line).append(endl);
    			collectionIdentifiant.add(line.substring(2, 11));
    		}
     
    		while ((line = buffFichier2.readLine()) != null) {
    			String ref = line.substring(2, 11);
    			if (!collectionIdentifiant.contains(ref))
    				fileMergeWriter.append(line).append(endl);
    		}
     
    		fileMergeWriter.flush();
     
    	}
     
    } catch (IOException ioe) {
    	// ce serait peut-être mieux de planter le programme. Non ?
    	throw new RuntimeException(ioe);
    }

    a++

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Octobre 2011
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 3
    Par défaut
    Ok merci beaucoup,
    J'étais justement en train de revoir tout ça et ça m'aide beaucoup, j'améliore tout ça et je reviens.

    Re: bon bah au final je n'ai pas amélioré grand chose ton code était très bien j'ai juste remplacer le bufferedReader par:
    BufferedReader buffFichier2 = new BufferedReader(new InputStreamReader(new FileInputStream(filePathFichier2), "ISO-8859-1"));
    Merci encore,

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

Discussions similaires

  1. Transfert de fichiers volumineux par le net
    Par K-Kaï dans le forum Général Conception Web
    Réponses: 8
    Dernier message: 14/07/2008, 13h15
  2. [Système] Système d'envoi de fichier volumineux
    Par mister3957 dans le forum Langage
    Réponses: 1
    Dernier message: 18/01/2007, 20h36
  3. Comment compresser les fichiers volumineux ?
    Par ThanosT dans le forum Framework .NET
    Réponses: 4
    Dernier message: 26/09/2006, 15h44
  4. XP PRO SP2 detection de fichiers volumineux
    Par HOFER dans le forum Windows XP
    Réponses: 3
    Dernier message: 14/08/2006, 12h47
  5. Chargement fichier volumineux
    Par kirsoul dans le forum Installation
    Réponses: 2
    Dernier message: 26/07/2005, 14h53

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