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


188

Je lis un fichier local en utilisant un BufferedReader enroulé autour d'un FileReader:

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

Ai-je besoin de close()la FileReadermême ou sera la poignée wrapper qui? 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 à partir d'un servlet, et je voudrais m'assurer de ne laisser aucune poignée ouverte.


4
Vous savez, vous pouvez simplement lire la source pour des informations comme celle-ci. Tout est là dans src.zip dans le répertoire d'installation de JDK, ou vous pouvez le lire en ligne par exemple sur docjar.com/html/api/java/io/BufferedReader.java.html
gustafc

50
Dire à quelqu'un de lire la source est pire que de dire "RTFM!". Et si la source a un bogue; implicitement, nous voulons savoir quel est le comportement correct ?
Raedwald

1
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 de bogue causant qu'elle ne se comporte pas comme elle est spécifiée dans les documents, vous ne pouvez pas vous fier aux documents. Il n'y a donc pas de bonne façon de répondre à une telle question.
Atmocreations

@Atmocreations La prochaine version de maintenance peut joyeusement corriger un bogue sur lequel vous comptez si vous regardez simplement la source. Vous avez vraiment besoin de savoir quel est le comportement documenté. Rien de mal à regarder la source, bien sûr, mais vous ne pouvez pas supposer que la source ne changera pas. Changer le comportement documenté est généralement bien plus important que de corriger un bogue.
James Moore le

Réponses:


202

non.

BufferedReader.close()

ferme le flux selon javadoc pour BufferedReader et InputStreamReader

aussi bien que

FileReader.close()

Est-ce que.


12
Sauf si le constructeur BufferedReaderlève une exception. Il est plus propre de fermer le flux sous-jacent, même si vous devez faire attention aux décorateurs avec d'autres ressources et tampons.
Tom Hawtin - tackline

9
Le Javadoc ne dit pas si BufferedReader.close()ferme le lecteur sous-jacent. Sa description est simplement copiée Reader.close(). Cela peut être le comportement réel dans la pratique, mais il n'est pas documenté.
John Kugelman

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

6
Peu importe si la documentation réelle aurait dû être modifiée ou ne pas avoir été modifiée, Reader#close()les javadoc de ne disent pas si oui ou non il ferme le Reader encapsulé ou non. Tout ce qu'il dit lié à cela, c'est Closes the stream and releases any system resources associated with it.ce qui n'est pas assez explicite pour dire qu'il ferme ou non la ressource. «Libérer la ressource» peut tout aussi bien supprimer toute référence à la ressource dans BufferedReader ... ce qui signifierait que la ressource n'est pas fermée.
searchengine27

99

Comme d'autres l'ont souligné, il vous suffit de fermer l'emballage extérieur.

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

Il y a de très faibles chances que cela puisse faire fuir un descripteur de fichier si le BufferedReaderconstructeur lançait une exception (par exempleOutOfMemoryError ). Si votre application est dans cet état, le degré de précision de votre nettoyage peut dépendre du degré critique de ne pas priver le système d'exploitation des ressources qu'il souhaite allouer à d'autres programmes.

L' interface Closeable peut être utilisée si un constructeur d'encapsuleur 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 le modèle try-with-resources :

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

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

5

Selon la source de BufferedReader, dans ce cas, bReader.close appelle fReader.close pour que techniquement vous n'ayez pas à appeler ce dernier.


Étant donné qu'il existe une documentation expliquant comment il doit être utilisé, vous devriez d'abord consulter la documentation - toute déviation dans le code est un bogue.
hmijail pleure les résignés le

5

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


1
Je veux vraiment donner un coup de pouce pour créer un lien vers quelque chose de concret, mais cela ne fait référence qu'à l'implémentation d'OpenJDK, et comme les JavaDocs ne sont pas clairs Reader#close(), cela ne prouve pas concrètement que le JDK Oracle, par exemple, est implémenté dans un de façon similaire.
searchengine27

4

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 l' objet BufferedReader appellerait la méthode abstraite close () de la classe Reader qui appellerait finalement la méthode implémentée dans la classe InputStreamReader , qui ferme ensuite l' objet InputStream .

Donc, seul bReader.close () est suffisant.


4
Ce que le code source montre ne peut pas être cité comme référence. C'est ce que dit la spécification , dans ce cas le Javadoc, sur lequel on peut se fier.
Marquis of Lorne

1

À partir de Java 7, vous pouvez utiliser l' instruction try-with-resources

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
}

Étant donné que l' BufferedReaderinstance est déclarée dans une instruction try-with-resource, elle sera fermée, que l'instruction try se termine normalement ou brusquement. Vous n'avez donc pas besoin de le fermer vous-même dans la finallydéclaration. (C'est également le cas des instructions de ressources imbriquées)

C'est la manière recommandée de travailler avec les ressources, voir la documentation pour plus d'informations


C'est presque identique à la réponse de @ mcdowell de 2009, qui couvre également certains problèmes marginaux qui pourraient survenir.
tresf le

0

Vous avez seulement besoin de fermer le bufferedReader ie reader.close () et cela fonctionnera très bien.


0

Je suis en retard, mais:

BufferReader.java:

public BufferedReader(Reader in) {
  this(in, defaultCharBufferSize);
}

(...)

public void close() throws IOException {
    synchronized (lock) {
        if (in == null)
            return;
        try {
            in.close();
        } finally {
            in = null;
            cb = null;
        }
    }
}

Eeeeh qui ne répond pas à sa question? Elle / Il demande s'il est nécessaire de fermer FileReader et BufferedReader pas un exemple de code.
TornaxO7

@ TornaxO7 non, ce n'est pas un exemple de code. Je viens d'écrire une partie du code source java. Donc, si vous cliquez sur une fonction de BufferedReader avec la touche ctrl / cmd (dépend de l'EDI), vous pouvez voir le code source de BufferedReader, et vous pouvez trouver ce fragment de code. Ainsi, comme vous pouvez le voir, BufferedReader ferme simplement FileReader par lui-même ('in' est FileReader dans ce cas, donc, lorsque vous appelez bufferReader.close (), il appelle in.close () à l'intérieur, exactement dans la méthode bufferReader.close)
Dmitry Gashko

0

Vous n'avez pas besoin de fermer le lecteur / graveur enveloppé.

Si vous avez jeté un œil à la documentation ( Reader.close(), Writer.close()), vous verrez que Reader.close()cela dit:

Ferme le flux et libère toutes les ressources système qui lui sont associées.

Ce qui dit simplement qu'il "libère toutes les ressources système qui lui sont associées ". Même si cela ne confirme pas ... cela vous donne un coup de pouce pour commencer à chercher plus profondément. et si vous allez àWriter.close() il indique seulement qu'il se ferme.

Dans de tels cas, nous nous référons à OpenJDK pour jeter un œil au code source.

À BufferedWriter Line 265, vous verrez out.close(). Donc ça ne se ferme pas… C'est autre chose. Si vous recherchez dans la classe des occurrences de " out", vous remarquerez que dans le constructeur à la ligne 87 qui outest l'écrivain, la classe s'enroule là où elle appelle un autre constructeur, puis attribue un outparamètre à son propreout variable.

Alors ... Et les autres? Vous pouvez voir un code similaire sur BufferedReader Line 514 , BufferedInputStream Line 468 et InputStreamReader Line 199 . D'autres je ne sais pas mais cela devrait suffire à supposer qu'ils le font.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.