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

Collection et Stream Java Discussion :

Fusionner 3 fichiers via Input/Output Stream


Sujet :

Collection et Stream Java

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 10
    Points : 3
    Points
    3
    Par défaut Fusionner 3 fichiers via Input/Output Stream
    Bonjour,
    Alors voila j'ai un petit soucis/interrogation.

    Je veux partir de 3 fichiers et les fusionner en un seul, et j'ai réussi mais il se passe un comportement etrange, alors plutot que de le contourner "a la main", je voudrais comprendre le pourquoi...

    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
     
    //existence du fichier dictionnaire
    java.io.File dico = new java.io.File("dictionnaryTest.txt");
    	if (dico.exists()== false){
    		myOutputDico = new FileOutputStream("dictionnaryTest.txt");
     
    		//cas ou le fichier dico n'existe pas, on le copie
     
    		myInputDico1 = new FileInputStream(NAME_DICO);
    		myInputDico2 = new FileInputStream(NAME_DICO2);
    		myInputDico3 = new FileInputStream(NAME_DICO3);
     
    				 copy(myInputDico1,myInputDico2,myInputDico3,myOutputDico);
    }
    et la méthode copy :

    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
     
    private static void copy(InputStream inputStream1, InputStream  inputStream2, InputStream inputStream3, FileOutputStream outputFile) {
     
    		BufferedOutputStream bufOut = new BufferedOutputStream(outputFile, 8192);
    		BufferedInputStream bufIn1 = new BufferedInputStream(inputStream1, 8192);
    		BufferedInputStream bufIn2 = new BufferedInputStream(inputStream2, 8192);
    		BufferedInputStream bufIn3 = new BufferedInputStream(inputStream3, 8192);
     
    		byte buf[] = new byte[8192];
     
    		int len;
     
    		try {
     
    			while ((len = bufIn1.read(buf)) != -1) {
     
    				bufOut.write(buf, 0, len);
     
    			}
     
     
    			while ((len = bufIn2.read(buf)) != -1) {
     
    				bufOut.write(buf, 0, len);
     
    			}
     
     
    			while ((len = bufIn3.read(buf)) != -1) {
     
    				bufOut.write(buf, 0, len);
     
    			}
    			bufOut.flush();
     
     
    			bufOut.close();
     
    			bufIn1.close();
    			bufIn2.close();
    			bufIn3.close();
     
    		} catch (IOException e) {
     
    		}	
    	}
    Donc le soucis c'est que la 1ere ligne (en l'occurence le 1er mot vu que c'est un mot par ligne) des 2 sous fichiers dico2 et dico3 sont ignorés, en debug, "len" prend bien la bonne valeur du nombre a écrire mais il n'ecrit simplement pas le debut dans le fichier en output... donc j'ai trouvé comme solution simplement de sauter la 1ere ligne des 2eme et 3eme fichiers, et la impec ça a bien tout fusionner, mais je comprends pas pourquoi il rate ainsi des données ...

    Merci

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


    Tu pourrais donner un exemple avec de résultats avec de petits fichiers ?
    Tu es sûr que ce n'est pas simplement un retour à la ligne manquant à la fin du fichier qui fait remonter la ligne à la fin de la dernière du fichier précédent.


    Sinon quelques remarques concernant ton code :
    • Il faut utiliser des try/finally pour la fermeture des fichiers !
    • Il ne faut jamais ignoré une exception !!!
    • Cela ne sert à rien d'utiliser des Buffered*Stream si tu utilises ton propre buffer.
    • On ne sait pas où sont déclarées tes variables myOutputDico/MyInputDico*. Ce devrait être des variables locales déclaré en lignes, et suivi du try/finally de fermeture...



    a++

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 10
    Points : 3
    Points
    3
    Par défaut
    Tout d'abord merci de repondre

    Alors :
    -en effet je sais que faut les mettre en finally, la j'avoue avoir un peu zapper, c'est moche

    -l'exception je ne l'ignore pas, en fait ce code est issue d'un code que je fais sur android que j'ai adapté "a la va vite" sur du java "normal" pour voir si il y avait le meme probleme, et oui, d'ou les petites remarques, et notamment le catch (sur la version android, j'ecris dans un Log special)

    -remarque liée a la premiere, je les declare juste au dessus du code cité, mais en effet en local dans le try serait plus propre

    Concernant la solution, en effet, les fichiers n'ont pas de retour a la ligne final, ils se terminent sur le dernier mot listé, mais alors pourquoi faut-il un retour a la ligne ?

  4. #4
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Citation Envoyé par Mikiya Voir le message
    mais alors pourquoi faut-il un retour a la ligne ?
    Parce que tu veux qu'il y ait un retour à la ligne. Les fichiers sont recopiés tels que, sans ajouter de retour à la ligne là où il n'y en a pas. Or, apparemment, tu veux qu'il y ait un retour à la ligne. Si tu n'en avais pas envie, il n'y en aurait pas besoin.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 10
    Points : 3
    Points
    3
    Par défaut
    Non justement, je veux que les 3 fichiers s’enchaînent dans un fichier final sans arrêts ni sauts, hors la, il me saute la 1ere ligne (enfin le 1er mot listé) des 2eme et 3eme fichiers, d'où ma solution temporaire mais "crade" de sauter une ligne au debut de ces fichiers la pour qu'il "rate" la ligne vide et ainsi ne perde pas de mots, mais je voudrais idéalement ne pas avoir a faire cette "bidouille".

  6. #6
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    J'ai parlé des retours à la ligne finaux, pas des retours à la ligne initiaux.

    En résumé, Java ne va pas inventer tout seul de retour à la ligne là où il n'y en a pas. Donc, si tu en veux un entre tes deux fichiers, il faut bien qu'il soit quelque part.
    À la fin du précédent ou au début du suivant, c'est toi qui voit. Mais en général, l'usage est qu'un fichier texte se termine toujours par un retour à la ligne.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 10
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par thelvin Voir le message
    J'ai parlé des retours à la ligne finaux, pas des retours à la ligne initiaux.

    En résumé, Java ne va pas inventer tout seul de retour à la ligne là où il n'y en a pas. Donc, si tu en veux un entre tes deux fichiers, il faut bien qu'il soit quelque part.
    À la fin du précédent ou au début du suivant, c'est toi qui voit. Mais en général, l'usage est qu'un fichier texte se termine toujours par un retour à la ligne.
    Je sais bien qu'il invente rien
    Mais non je ne veux aucun retour a la ligne dans le fichier final, avoir ajouter des retours a la ligne initiaux dans les fichiers dico2 et dico3 m'a simplement permis de contourner ce problème (sans le resoudre), car en mettant cette ligne vide au debut des fichiers, dans le fichier final, j'ai pas de ligne vide (et si je les mets pas, il n'y a pas non plus de ligne vide mais il manque 2 mots).

  8. #8
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Arrête de répondre sans arrêt "non tu n'as pas compris j'ai raison," et analyse un peu ce que je dis.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 10
    Points : 3
    Points
    3
    Par défaut
    Ne t’énerves pas, évites de me donner ainsi des ordres, je ne t'ai pas agressé, je te redis juste clairement la situation comme quoi je ne voulais pas de saut vide.


    @adiGuba : en effet, mettre un retour a la fin des fichiers a eu le meme effet que celui en debut du suivant. En fusionnant 3 fichiers avec la liste de mots + un retour a la ligne a la fin, j'obtient 1 fichier avec tout listé sans ligne vide et sans raté.

    Mais je commence a comprendre le soucis, je n'avais pas vérifié a l’époque, mais surement que les 2 mots "ratés" avaient en fait étaient concaténés au mot de la ligne finale du fichier précedent, ce qui apparait comme normal après coup ^^ merci bien, assez bete la pour le coup l'oublie.

  10. #10
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Citation Envoyé par Mikiya Voir le message
    Ne t’énerves pas, évites de me donner ainsi des ordres, je ne t'ai pas agressé, je te redis juste clairement la situation comme quoi je ne voulais pas de saut vide.
    Je ne m'énerve pas, c'est juste que tu n'as pas compris un traître mot de ce que j'ai raconté, alors que ce n'est pas spécialement compliqué et que ça expliquait tout, répondant à la question que tu te posais.
    Si tu ne le comprenais pas, c'est parce que tu refusais de comprendre autre chose que ce que tu pensais déjà, et donc n'analysais pas beaucoup ce que je disais.
    Pour t'aider à comprendre, je t'ai donc dit de cesser de faire ça.

    Je constate que tu as fini par te sortir de ta boucle infernale et de comprendre ce qui se passe, parfait. Tu y es arrivé tout seul, c'est très bien.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  11. #11
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Mikiya Voir le message
    -en effet je sais que faut les mettre en finally, la j'avoue avoir un peu zapper, c'est moche
    Oui mais c'est obligatoire tant qu'on ne pourras pas faire joujou avec Java 7...

    Dans ton code les fichiers ne sont pas fermées en cas d'exception

    Citation Envoyé par Mikiya Voir le message
    -l'exception je ne l'ignore pas, en fait ce code est issue d'un code que je fais sur android que j'ai adapté "a la va vite" sur du java "normal" pour voir si il y avait le meme probleme, et oui, d'ou les petites remarques, et notamment le catch (sur la version android, j'ecris dans un Log special)
    En même temps le catch est super mal positionnée.
    Non seulement les fichiers ne sont pas fermés mais en plus tu ne peux pas détecter cela dans ton programme au retour de la méthode copy...

    Citation Envoyé par Mikiya Voir le message
    Concernant la solution, en effet, les fichiers n'ont pas de retour a la ligne final, ils se terminent sur le dernier mot listé, mais alors pourquoi faut-il un retour a la ligne ?
    As-tu vérifié le contenu de ces dernières lignes ? Avec de petits fichiers ?

    Si tu copies 3 fichiers sans fin de lignes finales :
    Lors de la jointure cela donnera forcément quelque chose comme cela :

    Donc dans ce cas tu est bien obligé de rajouter une fin de ligne...


    a++

  12. #12
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 10
    Points : 3
    Points
    3
    Par défaut
    en effet mais sur la methode version android la methode copy a cette tete la en vrai (après avoir viré les buffer qui etaient inutiles comme t'as fais remarqué ) :

    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
     
    private void copy(InputStream inputStream1, InputStream inputStream2, InputStream inputStream3, FileOutputStream outputFile) throws IOException {
     
    		byte buf[] = new byte[8192];
     
    		int len;
     
    			try {
    				while ((len = inputStream1.read(buf)) != -1) {		  
    					outputFile.write(buf, 0, len);	  
    				}
     
    				while ((len = inputStream2.read(buf)) != -1) {				  
    					outputFile.write(buf, 0, len);
    				}
     
     
    				while ((len = inputStream3.read(buf)) != -1) {		  
    					outputFile.write(buf, 0, len);
    				}
    				outputFile.flush();
    			}
    			finally {
    				outputFile.close();
    				inputStream1.close();
    				inputStream2.close();
    				inputStream3.close();
     
    		}
    	}
    en tout cas merci des conseils et de l'explication, ayant 387 000 mots, j'avais a ce moment pas remarqué que 2 mots avaient été concatenés.

    edit : tiens d'ailleurs j'en profite pour demander un truc : les close dans copy(...) sur les inputstream passés en parametres, ça ferme aussi les streams dans le programme appelant (en gros ils pointent sur le meme objets) ou bien on travail sur des copies des streams ?

  13. #13
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    bref c'est ce que thelvin se tue à dire depuis le début

  14. #14
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Citation Envoyé par Mikiya Voir le message
    edit : tiens d'ailleurs j'en profite pour demander un truc : les close dans copy(...) sur les inputstream passés en parametres, ça ferme aussi les streams dans le programme appelant (en gros ils pointent sur le meme objets) ou bien on travail sur des copies des streams ?
    Méthode appelante et méthode appelée font toutes les deux parties du même programme .

    Quant aux InputStream, et comme n'importe quel objet, ce sont les mêmes, ils ne sont pas copiés. Un close() de l'appelé fermera l'InputStream pour tout le code qui a une référence vers elle, parce qu'elle est seule et unique.
    Autrement dit, le faire une fois suffit (et d'ailleurs le faire plusieurs fois échoue.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  15. #15
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 10
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Méthode appelante et méthode appelée font toutes les deux parties du même programme .

    Quant aux InputStream, et comme n'importe quel objet, ce sont les mêmes, ils ne sont pas copiés. Un close() de l'appelé fermera l'InputStream pour tout le code qui a une référence vers elle, parce qu'elle est seule et unique.
    Autrement dit, le faire une fois suffit (et d'ailleurs le faire plusieurs fois échoue.)
    Merci bien, j'avais un doute vis a vis du C la avec les adresses/valeurs et bien merci, vais pouvoir continuer tout ça, ça roule ^^

  16. #16
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Quelques remarques (et oui encore !) :

    • Il faut un try/finally par ressource. Sinon en cas d'erreur sur une des ressources il est possible que les autres ne soient pas correctement fermées
    • On peut fermer un flux reçu en paramètre, mais personnellement je conseillerait plutôt de le faire là où il a été créé.
      En clair celui qui crée une ressource est responsable de sa fermeture !



    Tu n'as pas posté le code d'appel, mais je suis persuadé qu'il y a plusieurs cas d'erreurs où tes ressources ne serait pas correctement fermées.


    a++

  17. #17
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 10
    Points : 3
    Points
    3
    Par défaut
    J'ai deja modifié le code suite a la reponse de thelvin pour que ce soit bien l'appelant qui ferme ses stream, comme tu dis, c'est plus logique oui

    Sinon je ne savais pas pour le try/finally pour chaque, je faisais a chaque fois ainsi, un finally globale des ressources. Du coup oui je vais en mettre pour chaque merci de l'info

  18. #18
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Mikiya Voir le message
    Sinon je ne savais pas pour le try/finally pour chaque, je faisais a chaque fois ainsi, un finally globale des ressources. Du coup oui je vais en mettre pour chaque merci de l'info
    L'utilisation d'un try/finally par ressource permet d'avoir un code sûr en suivant toujours le même pattern, et donc cela permet d'éviter les erreurs.

    Avec un seul finally pour plusieurs ressources on ne peut pas s'assurer de la bonne fermeture des ressources dans tous les cas.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    	FileOutputStream o = new FileOutputStream("o");
    	FileInputStream i1 = new FileInputStream("i1");
    	FileInputStream i2 = new FileInputStream("i2");
    	FileInputStream i3 = new FileInputStream("i3");
    	try {
    		// ...
    	} finally {
    		o.close();
    		i1.close();
    		i2.close();
    		i3.close();
    	}
    Cas d'erreurs :
    • Si une des méthodes close() génèrent une exception, les ressources suivantes ne seront pas fermées !
    • Si la création d'une ressources échoues (FileNotFound par exemple), on ne rentre pas dans le finally puisqu'on n'est pas rentré dans le try.


    Il faudrait déplacer toutes les ouvertures/fermetures de flux dans le bloc try, et multiplier les vérifications dans le code du finally qui deviendrait véritablement imbitable si on veut faire propre (et ne pas ignorer les erreurs de fermeture) :
    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
    FileOutputStream o = null;
    	FileInputStream i1 = null;
    	FileInputStream i2 = null;
    	FileInputStream i3 = null;
    	try {
    		o = new FileOutputStream("o");
    		i1 = new FileInputStream("i1");
    		i2 = new FileInputStream("i2");
    		i3 = new FileInputStream("i3");
     
    		// ...
    	} finally {
    		IOException lastError = null;
    		if (o!=null) {
    			try {
    			o.close();
    			} catch(IOException e) {
    				lastError = e;
    			}
    		}
    		if (i1!=null) {
    			try {
    				i1.close();
    			} catch(IOException e) {
    				lastError = e;
    			}
    		}
    		if (i2!=null) {
    			try {
    				i2.close();
    			} catch(IOException e) {
    				lastError = e;
    			}
    		}
    		if (i3!=null) {
    			try {
    				i3.close();
    			} catch(IOException e) {
    				lastError = e;
    			}
    		}
    		if (lastError!=null)
    			throw lastError;
    	}
    Sans parler que le code du finally peut varier selon les ressources et comment tu les crées




    Avec la règle d'un try/finally par ressources on augmente peut-être l'indentation mais on s'assure d'un code sécurisé :
    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
    	FileOutputStream o = new FileOutputStream("o");
    	try {
    		FileInputStream i1 = new FileInputStream("i1");
    		try {
    			FileInputStream i2 = new FileInputStream("i2");
    			try {
    				FileInputStream i3 = new FileInputStream("i3");
    				try {
    					// ...
    				} finally {
    					i3.close();
    				}
    			} finally {
    				i2.close();
    			}
    		} finally {
    			i1.close();
    		}
    	} finally {
    		o.close();
    	}
    Si la création de la ressource est OK, on rentre dans son try/finally qui garantie l'appel à la méthode de fermeture au plus tôt et dans tous les cas...


    Le seul problème de cette dernière solution concerne la propagation des exceptions.
    Si le bloc finally génère une exception alors que son bloc try en a généré une autre, cette dernière est totalement perdu. Il y a des solution pour éviter cela mais le code n'en devient que plus lourd !
    (note : le problème existe aussi dans le premier cas - il faudra attendre Java 7 pour une solution optimum).



    A noter que dans ton cas on n'a pas besoin de toutes les ressources en même temps, donc cela pourrait donner 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
    	FileOutputStream o = new FileOutputStream("o");
    	try {
    		FileInputStream i1 = new FileInputStream("i1");
    		try {
    			// ...
    		} finally {
    			i1.close();
    		}
     
    		FileInputStream i2 = new FileInputStream("i2");
    		try {
    			// ...
    		} finally {
    			i2.close();
    		}
     
    		FileInputStream i3 = new FileInputStream("i3");
    		try {
    			// ...
    		} finally {
    			i3.close();
    		}
    	} finally {
    		o.close();
    	}


    Et pour info, dans Java 7 il suffira d'utiliser un seul et unique bloc try :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    // Code Jave 7
    	try (FileOutputStream o = new FileOutputStream("o");
    	  FileInputStream i1 = new FileInputStream("i1");
    	  FileInputStream i2 = new FileInputStream("i2");
    	  FileInputStream i3 = new FileInputStream("i3")) {
    		// ...
    	}

    a++

  19. #19
    Membre expérimenté

    Inscrit en
    Décembre 2004
    Messages
    584
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 584
    Points : 1 374
    Points
    1 374
    Par défaut
    Nous on a un simple IOHelper.tryToClose(..) qui s'occupe de clore nos streams.

    Du coup:
    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
     
    } finally {
    		IOException lastError = null;
    		if (o!=null) {
    			try {
    			o.close();
    			} catch(IOException e) {
    				lastError = e;
    			}
    		}
    		if (i1!=null) {
    			try {
    				i1.close();
    			} catch(IOException e) {
    				lastError = e;
    			}
    		}
    		if (i2!=null) {
    			try {
    				i2.close();
    			} catch(IOException e) {
    				lastError = e;
    			}
    		}
    		if (i3!=null) {
    			try {
    				i3.close();
    			} catch(IOException e) {
    				lastError = e;
    			}
    		}
    		if (lastError!=null)
    			throw lastError;
    	}
    devient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    } finally {
    		IOHelper.tryToClose(o);
    		IOHelper.tryToClose(i1);
    		IOHelper.tryToClose(i2);
    		IOHelper.tryToClose(i3);
    	}
    on ignore les éventuelles erreurs dans les "tryToClose" vu que l'appellant ne peut rien y faire généralement.

    On peut envisager de mettre des logs dans la classe IOHelper pour savoir quand un tel problème apparait.
    Merci d'utiliser le bouton [Résolu] pour les sujets qui le sont.
    [pub]mon blog franco anglais, article du moment: Wicket: fournir des données JSON via Ajax[/pub]

  20. #20
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par joseph_p Voir le message
    on ignore les éventuelles erreurs dans les "tryToClose" vu que l'appellant ne peut rien y faire généralement.
    Je l'attendais celle là

    Donc en gros en cas de problème on ignore l'erreur et on continue le traitement comme si de rien n'était. Voilà une belle manière de perdre des données !



    A la rigueur j'aurais accepté quelque chose comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    } finally {
    		IOException lastError = IOHelper.tryToClose(o);
    		lastError = IOHelper.tryToClose(i1, lastError);
    		lastError = IOHelper.tryToClose(i2, lastError);
    		lastError = IOHelper.tryToClose(i3, lastError);
    		if (lastError!=null)
    			throw lastError;
    	}
    Mais je continuerais à conseiller l'usage d'un try/finally par ressource...


    a++

Discussions similaires

  1. Réponses: 4
    Dernier message: 28/08/2014, 18h30
  2. Input-Output Stream et réseau
    Par warseb dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 27/02/2008, 20h36
  3. Obtenir la taille d'un fichier selectionné via input
    Par Tchupacabra dans le forum Général JavaScript
    Réponses: 13
    Dernier message: 29/06/2007, 08h54
  4. Cipher Input/Output Stream
    Par Razgriz dans le forum Sécurité
    Réponses: 16
    Dernier message: 13/05/2007, 16h32
  5. Problème input/output fichier
    Par nenekes dans le forum Cobol
    Réponses: 3
    Dernier message: 09/09/2006, 22h54

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