207 votes

Dois-je fermer() à la fois le FileReader et le BufferedReader ?

Je lis un fichier local à l'aide d'un BufferedReader enveloppé dans un FileReader :

BufferedReader reader = new BufferedReader(new FileReader(fileName));
// read the file
// (error handling snipped)
reader.close();

Dois-je close() le site FileReader ou le wrapper s'en chargera-t-il ? J'ai vu du code où les gens font quelque chose comme ça :

FileReader fReader = new FileReader(fileName);
BufferedReader bReader = new BufferedReader(fReader);
// read the file
// (error handling snipped)
bReader.close();
fReader.close();

Cette méthode est appelée depuis une servlet, et je voudrais m'assurer que je ne laisse pas de handles ouverts.

4 votes

Tu sais, tu peux juste lire la source pour ce genre d'info. Tout est là, dans src.zip, dans le répertoire d'installation du JDK, ou vous pouvez le lire en ligne, par exemple à l'adresse suivante docjar.com/html/api/java/io/BufferedReader.java.html

57 votes

Dire à quelqu'un de lire la source est pire que de lui dire "RTFM !". Et que se passe-t-il si la source a un bug ; implicitement, nous voulons savoir ce que le correct comportement est ?

1 votes

Eh bien ... de ce point de vue : pointer vers les spécifications de l'API n'est pas mieux alors. Si la source n'a pas un bogue qui fait qu'elle ne se comporte pas comme il est spécifié dans les docs, vous ne pouvez pas vous fier aux docs. Il n'y a donc pas de bonne façon de répondre à une telle question.

215voto

Atmocreations Points 3300

Non.

BufferedReader.close()

ferme le flux selon la javadoc pour BufferedReader et InputStreamReader

ainsi que

FileReader.close()

fait.

13 votes

Sauf si le constructeur de BufferedReader lance une exception. Il est plus propre de fermer simplement le flux sous-jacent, bien que vous deviez faire attention aux décorateurs avec d'autres ressources et tampons.

10 votes

La Javadoc ne précise pas si BufferedReader.close() ferme le lecteur sous-jacent. Sa description est simplement copiée de Reader.close() . C'est peut-être le comportement réel dans la pratique, mais il n'est pas documenté.

4 votes

Si le comportement réel était différent, alors il aurait dû être documenté comme tel. Sinon, la documentation est inutile. Le programmeur doit pouvoir considérer la documentation comme complète et spécifique.

112voto

McDowell Points 62645

Comme d'autres l'ont souligné, il suffit de fermer l'enveloppe extérieure.

BufferedReader reader = new BufferedReader(new FileReader(fileName));

Il y a une très faible chance que cela fasse fuir un identifiant de fichier si l'option BufferedReader a déclenché une exception (p. ex. OutOfMemoryError ). Si votre application se trouve dans cet état, le soin que vous devez apporter au nettoyage dépend de l'importance que vous accordez à ne pas priver le système d'exploitation de ressources qu'il pourrait vouloir allouer à d'autres programmes.

Le site Fermable peut être utilisée si un constructeur wrapper est susceptible d'échouer dans Java 5 ou 6 :

Reader reader = new FileReader(fileName);
Closeable resource = reader;
try {
  BufferedReader buffered = new BufferedReader(reader);
  resource = buffered;
  // TODO: input
} finally {
  resource.close();
}

Le code Java 7 doit utiliser l'option essayer avec les ressources modèle :

try (Reader reader = new FileReader(fileName);
    BufferedReader buffered = new BufferedReader(reader)) {
  // TODO: input
}

3 votes

"Le code Java 7 devrait utiliser le modèle try-with-resources". Merci, c'est exactement ce que je cherchais. Cette solution a été écrite en 2009, donc le paradigme try-with-resources devrait probablement être la nouvelle recommandation. De plus, elle offre une meilleure réponse au PO que la réponse acceptée et plus votée.

1 votes

@tresf vient de chercher pendant 10 minutes pour essayer de trouver cette réponse, je suis tout à fait d'accord - montrer comment ouvrir le Filereader pour pouvoir le fermer plus tard est essentiel.

7voto

Brian Agnew Points 143181

Le code source de BufferedReader montre que le sous-jacent est fermé lorsque vous fermez le BufferedReader.

2 votes

J'ai vraiment envie de donner un coup de pouce à ce lien vers quelque chose de concret, mais il ne se réfère qu'à l'implémentation d'OpenJDK, et comme les JavaDocs ne sont pas claires pour les Reader#close() mais cela ne prouve pas concrètement que le JDK d'Oracle, par exemple, est mis en œuvre de manière similaire.

6voto

Csaba_H Points 5504

Selon la source de BufferedReader, dans ce cas, bReader.close appelle fReader.close, donc techniquement, vous n'avez pas besoin d'appeler ce dernier.

0 votes

Étant donné qu'il existe une documentation expliquant comment l'utiliser, vous devez d'abord consulter la documentation - toute déviation dans le code est un bogue.

5voto

Anup Verma Points 85

Après avoir vérifié le code source, j'ai trouvé que pour l'exemple :

FileReader fReader = new FileReader(fileName);
BufferedReader bReader = new BufferedReader(fReader);

la méthode close() sur BufferedReader appelle la méthode abstraite close() de l'objet Lecteur qui appellerait finalement la méthode implémentée dans InputStreamReader qui ferme ensuite la classe InputStream objet.

Ainsi, seul bReader.close() est suffisant.

5 votes

Ce que le code source montre n'est pas citable comme référence. C'est ce que le spécification dit, dans ce cas la Javadoc, sur laquelle on peut s'appuyer.

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