72 votes

Fermeture des flux d'entrée Java

J'ai quelques questions concernant l'utilisation de la méthode close() lors de l'utilisation de Java InputStreams. D'après ce que j'ai vu et lu chez la plupart des développeurs, il faut toujours appeler explicitement close() sur un InputStream lorsqu'il n'est plus nécessaire. Mais aujourd'hui, je me suis penché sur l'utilisation d'un fichier de propriétés Java, et tous les exemples que j'ai trouvés présentent quelque chose comme ceci :

Properties props = new Properties();
try {
    props.load(new FileInputStream("message.properties"));
    //omitted.
} catch (Exception ex) {}

Dans l'exemple ci-dessus, il n'y a aucun moyen d'appeler explicitement close() car l'InputStream est inaccessible après son utilisation. J'ai vu de nombreuses utilisations similaires d'InputStreams, même si cela semble contredire ce que la plupart des gens disent à propos de la fermeture explicite. J'ai lu les JavaDocs d'Oracle et il n'est pas mentionné si la méthode Properties.load() ferme l'InputStream. Je me demande si cela est généralement acceptable ou s'il est préférable de faire quelque chose comme ce qui suit :

Properties props = new Properties();
InputStream fis = new FileInputStream("message.properties");
try {
    props.load(fis);
    //omitted.
} catch (Exception ex) {
    //omitted.
} finally {
    try {
        fis.close();
    } catch (IOException ioex) {
        //omitted.
    }
}

Quelle voie est la meilleure et/ou la plus efficace ? Ou est-ce vraiment important ?

1 votes

Merci à tous pour les réponses que vous avez fournies. J'aimerais pouvoir les accepter toutes comme LA réponse. Cela a maintenant du sens pour moi.

50voto

Jon Points 23749

La classe Properties englobe le flux d'entrée dans un LineReader pour lire le fichier de propriétés. Puisque vous fournissez le flux d'entrée, il est de votre responsabilité de le fermer.

Le deuxième exemple est de loin la meilleure façon de gérer le flux, ne comptez pas sur quelqu'un d'autre pour le fermer à votre place.

Une amélioration que vous pourriez faire est d'utiliser IOUtils.closeQuietly()

pour fermer le flux, par exemple :

Properties props = new Properties();
InputStream fis = new FileInputStream("message.properties");
try {
    props.load(fis);
    //omitted.
} catch (Exception ex) {
    //omitted.
} finally {
    IOUtils.closeQuietly(fis);
}

5 votes

DON'T USE, déprécié et supprimé sans remplacement sur IOUtils 2.6. "Veuillez utiliser l'instruction try-with-resources ou gérer manuellement les exceptions supprimées".

42voto

Daniel Voina Points 1675

J'opterais pour un essai avec des ressources (au moins pour Java 7+) :

Properties props = new Properties();

try(InputStream fis = new FileInputStream("message.properties")) {
    props.load(fis);
    //omitted.
} catch (Exception ex) {
    //omitted.
}

Le site close() doit être appelé automatiquement à la sortie du bloc d'essai.

27voto

Bill the Lizard Points 147311

Les exemples de l Tutoriel sur les propriétés fermer le FileInputStream explicitement après le chargement, donc je pense qu'il est sûr de supposer que la load La méthode n'en est pas responsable, c'est vous qui l'êtes.

// create and load default properties
Properties defaultProps = new Properties();
FileInputStream in = new FileInputStream("defaultProperties");
defaultProps.load(in);
in.close();

Juste pour référence, j'ai vérifié le Apache Harmony mise en œuvre de Propriétés et c'est le cas pas fermer le flux au chargement.

0 votes

Le tutoriel sur les propriétés est l'explication que j'espérais. Merci pour le lien !

14voto

Adrian Smith Points 6087

Il n'est pas mentionné dans la documentation que props.load fermerait le flux d'entrée. Vous devez fermer le flux d'entrée manuellement dans un bloc finally comme vous le suggérez.

Il n'est pas normal pour une fonction de fermer une InputStream . La même convention s'applique qu'à la mémoire dans les langages sans collecte de données : Si possible, celui qui ouvre le flux doit fermer le flux. Sinon, il est très facile de laisser un flux ouvert (vous pensez qu'une fonction va le fermer, mais elle ne le fait pas, ou autre chose...).

0 votes

+1 à "celui qui ouvre le flux doit fermer le flux" Si cela n'est pas possible, le commentaire de la méthode doit indiquer à l'appelant de le faire. Le premier exemple de code est une mauvaise pratique.

0 votes

Le dernier correctif de Java 1.6 comporte ce commentaire pour props.load(Reader) : Le flux spécifié reste ouvert après le retour de cette méthode. Avant de trouver cette question-réponse, j'avais résumé les documents pour props.load(Reader) et ne comprenait pas pourquoi mon flux était encore ouvert !

7voto

Nathan Hughes Points 30377

Il semble que le premier exemple de code finisse par s'appuyer sur la méthode finalize de FileInputStream pour fermer réellement le fichier. Je dirais que votre deuxième exemple est meilleur, même si dans les deux cas le fichier est effectivement fermé.

Il y a des cas comme les flux d'octets où close ne fait rien et peut être omis, sinon je pense qu'il est préférable de fermer explicitement le fichier dans un bloc finally. Si vous l'ouvrez, vous le fermez.

Il y a un livre sur le site d'Oracle appelé Performances de la plate-forme Java qui traite des finaliseurs dans son annexe, il est dit :

Il est presque toujours préférable de faire son propre nettoyage plutôt que de s'en remettre à un finisseur. L'utilisation d'un finisseur peut également laisser derrière elle des ressources critiques qui ne seront pas récupérées avant un laps de temps indéterminé. Si vous envisagez d'utiliser un finisseur pour vous assurer que les ressources importantes sont libérées en temps voulu, vous devriez peut-être y réfléchir à deux fois.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X