Vous pouvez fermer le flux le plus externe, en fait vous n'avez pas besoin de conserver tous les flux encapsulés et vous pouvez utiliser Java 7 try-with-resources.
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new GZIPOutputStream(new FileOutputStream(createdFile)))) {
// write to the buffered writer
}
Si vous vous abonnez à YAGNI, ou si vous n'en avez pas besoin, vous ne devriez ajouter que le code dont vous avez réellement besoin. Vous ne devriez pas ajouter de code dont vous pensez avoir besoin, mais en réalité, cela ne fait rien d'utile.
Prenez cet exemple et imaginez ce qui pourrait mal tourner si vous ne le faisiez pas et quel en serait l'impact?
try (
OutputStream outputStream = new FileOutputStream(createdFile);
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
OutputStreamWriter osw = new OutputStreamWriter(gzipOutputStream);
BufferedWriter bw = new BufferedWriter(osw)
) {
// ...
}
Commençons par FileOutputStream qui appelle open
à faire tout le vrai travail.
/**
* Opens a file, with the specified name, for overwriting or appending.
* @param name name of file to be opened
* @param append whether the file is to be opened in append mode
*/
private native void open(String name, boolean append)
throws FileNotFoundException;
Si le fichier n'est pas trouvé, il n'y a pas de ressource sous-jacente à fermer, donc le fermer ne fera aucune différence. Si le fichier existe, il doit lancer une exception FileNotFoundException. Il n'y a donc rien à gagner en essayant de fermer la ressource à partir de cette seule ligne.
La raison pour laquelle vous devez fermer le fichier est lorsque le fichier est ouvert avec succès, mais vous obtenez plus tard une erreur.
Regardons le prochain flux GZIPOutputStream
Il y a du code qui peut lever une exception
private void writeHeader() throws IOException {
out.write(new byte[] {
(byte) GZIP_MAGIC, // Magic number (short)
(byte)(GZIP_MAGIC >> 8), // Magic number (short)
Deflater.DEFLATED, // Compression method (CM)
0, // Flags (FLG)
0, // Modification time MTIME (int)
0, // Modification time MTIME (int)
0, // Modification time MTIME (int)
0, // Modification time MTIME (int)
0, // Extra flags (XFLG)
0 // Operating system (OS)
});
}
Cela écrit l'en-tête du fichier. Maintenant, il serait très inhabituel pour vous de pouvoir ouvrir un fichier pour l'écriture mais de ne pas pouvoir y écrire même 8 octets, mais imaginons que cela puisse arriver et nous ne fermons pas le fichier par la suite. Qu'arrive-t-il à un fichier s'il n'est pas fermé?
Vous n'obtenez pas d'écritures non vidées, elles sont supprimées et dans ce cas, il n'y a pas d'octets écrits avec succès dans le flux qui n'est de toute façon pas mis en mémoire tampon à ce stade. Mais un fichier qui n'est pas fermé ne vit pas éternellement, FileOutputStream a
protected void finalize() throws IOException {
if (fd != null) {
if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
flush();
} else {
/* if fd is shared, the references in FileDescriptor
* will ensure that finalizer is only called when
* safe to do so. All references using the fd have
* become unreachable. We can call close()
*/
close();
}
}
}
Si vous ne fermez pas du tout un fichier, il se ferme de toute façon, mais pas immédiatement (et comme je l'ai dit, les données qui sont laissées dans un tampon seront perdues de cette façon, mais il n'y en a pas à ce stade)
Quelle est la conséquence de ne pas fermer le dossier immédiatement? Dans des conditions normales, vous risquez de perdre certaines données et vous risquez de manquer de descripteurs de fichiers. Mais si vous avez un système où vous pouvez créer des fichiers mais que vous ne pouvez rien y écrire, vous avez un problème plus grave. c'est-à-dire qu'il est difficile d'imaginer pourquoi vous essayez à plusieurs reprises de créer ce fichier malgré le fait que vous échouez.
OutputStreamWriter et BufferedWriter ne lancent pas d'exception IOException dans leurs constructeurs, de sorte que le problème qu'ils provoqueraient n'est pas clair. Dans le cas de BufferedWriter, vous pouvez obtenir une OutOfMemoryError. Dans ce cas, il déclenchera immédiatement un GC qui, comme nous l'avons vu, fermera quand même le fichier.