Sie können den äußersten Stream schließen. Tatsächlich müssen Sie nicht alle umschlossenen Streams beibehalten, und Sie können Java 7 Try-with-Resources verwenden.
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new GZIPOutputStream(new FileOutputStream(createdFile)))) {
// write to the buffered writer
}
Wenn Sie YAGNI abonnieren oder es nicht brauchen, sollten Sie nur den Code hinzufügen, den Sie tatsächlich benötigen. Sie sollten keinen Code hinzufügen, von dem Sie sich vorstellen, dass Sie ihn benötigen, aber in Wirklichkeit tun Sie nichts Nützliches.
Nehmen Sie dieses Beispiel und stellen Sie sich vor, was möglicherweise schief gehen könnte, wenn Sie dies nicht tun würden und welche Auswirkungen dies hätte.
try (
OutputStream outputStream = new FileOutputStream(createdFile);
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
OutputStreamWriter osw = new OutputStreamWriter(gzipOutputStream);
BufferedWriter bw = new BufferedWriter(osw)
) {
// ...
}
Beginnen wir mit FileOutputStream, der aufruft, open
um die gesamte eigentliche Arbeit zu erledigen.
/**
* 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;
Wenn die Datei nicht gefunden wird, muss keine zugrunde liegende Ressource geschlossen werden, sodass das Schließen keinen Unterschied macht. Wenn die Datei vorhanden ist, sollte eine FileNotFoundException ausgelöst werden. Es gibt also nichts zu gewinnen, wenn versucht wird, die Ressource allein aus dieser Zeile zu schließen.
Der Grund, warum Sie die Datei schließen müssen, ist, wenn die Datei erfolgreich geöffnet wurde, aber später eine Fehlermeldung angezeigt wird.
Schauen wir uns den nächsten Stream an GZIPOutputStream
Es gibt Code, der eine Ausnahme auslösen kann
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)
});
}
Dies schreibt den Header der Datei. Jetzt wäre es sehr ungewöhnlich, dass Sie eine Datei zum Schreiben öffnen können, aber nicht einmal 8 Bytes darauf schreiben können. Stellen Sie sich jedoch vor, dass dies passieren könnte und wir die Datei danach nicht schließen. Was passiert mit einer Datei, wenn sie nicht geschlossen ist?
Sie erhalten keine nicht geleerten Schreibvorgänge, sie werden verworfen, und in diesem Fall gibt es keine erfolgreich geschriebenen Bytes in den Stream, die zu diesem Zeitpunkt ohnehin nicht gepuffert sind. Aber eine Datei, die nicht geschlossen ist, lebt nicht für immer, sondern FileOutputStream
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();
}
}
}
Wenn Sie eine Datei überhaupt nicht schließen, wird sie trotzdem geschlossen, nur nicht sofort (und wie gesagt, Daten, die in einem Puffer verbleiben, gehen auf diese Weise verloren, aber zu diesem Zeitpunkt gibt es keine).
Was ist die Folge davon, dass die Datei nicht sofort geschlossen wird? Unter normalen Bedingungen verlieren Sie möglicherweise einige Daten, und Ihnen gehen möglicherweise die Dateideskriptoren aus. Wenn Sie jedoch ein System haben, in dem Sie Dateien erstellen, aber nichts darauf schreiben können, haben Sie ein größeres Problem. Das heißt, es ist schwer vorstellbar, warum Sie wiederholt versuchen, diese Datei zu erstellen, obwohl Sie einen Fehler machen.
Sowohl OutputStreamWriter als auch BufferedWriter lösen keine IOException in ihren Konstruktoren aus, sodass nicht klar ist, welches Problem sie verursachen würden. Im Fall von BufferedWriter könnten Sie einen OutOfMemoryError erhalten. In diesem Fall wird sofort ein GC ausgelöst, der, wie wir gesehen haben, die Datei trotzdem schließt.