Możesz zamknąć najbardziej zewnętrzny strumień, w rzeczywistości nie musisz zachowywać wszystkich opakowanych strumieni i możesz użyć Java 7 try-with-resources.
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new GZIPOutputStream(new FileOutputStream(createdFile)))) {
}
Jeśli subskrybujesz YAGNI lub nie będziesz go potrzebować, powinieneś dodawać tylko kod, którego faktycznie potrzebujesz. Nie powinieneś dodawać kodu, który Twoim zdaniem może być potrzebny, ale w rzeczywistości nie robi nic pożytecznego.
Weź ten przykład i wyobraź sobie, co mogłoby się nie udać, gdybyś tego nie zrobił i jaki byłby tego wpływ?
try (
OutputStream outputStream = new FileOutputStream(createdFile);
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
OutputStreamWriter osw = new OutputStreamWriter(gzipOutputStream);
BufferedWriter bw = new BufferedWriter(osw)
) {
}
Zacznijmy od FileOutputStream, który wywołuje open
całą prawdziwą pracę.
private native void open(String name, boolean append)
throws FileNotFoundException;
Jeśli plik nie zostanie znaleziony, nie ma bazowego zasobu do zamknięcia, więc zamknięcie go nie spowoduje żadnej różnicy. Jeśli plik istnieje, powinien generować wyjątek FileNotFoundException. Nie ma więc nic do zyskania, próbując zamknąć zasób tylko z tej linii.
Powodem, dla którego musisz zamknąć plik, jest pomyślne otwarcie pliku, ale później pojawia się błąd.
Spójrzmy na następny strumień GZIPOutputStream
Istnieje kod, który może zgłosić wyjątek
private void writeHeader() throws IOException {
out.write(new byte[] {
(byte) GZIP_MAGIC,
(byte)(GZIP_MAGIC >> 8),
Deflater.DEFLATED,
0,
0,
0,
0,
0,
0,
0
});
}
To zapisuje nagłówek pliku. Teraz byłoby bardzo nietypowe, gdybyś mógł otworzyć plik do zapisu, ale nie byłbyś w stanie zapisać do niego nawet 8 bajtów, ale wyobraźmy sobie, że może się to zdarzyć i nie zamykamy pliku później. Co się dzieje z plikiem, jeśli nie jest zamknięty?
Nie dostajesz żadnych niezapisanych zapisów, są one odrzucane iw tym przypadku nie ma pomyślnie zapisanych bajtów do strumienia, który i tak nie jest w tym momencie buforowany. Ale plik, który nie jest zamknięty, nie żyje wiecznie, zamiast tego FileOutputStream ma
protected void finalize() throws IOException {
if (fd != null) {
if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
flush();
} else {
close();
}
}
}
Jeśli w ogóle nie zamkniesz pliku, i tak zostanie on zamknięty, ale nie od razu (i jak powiedziałem, dane pozostawione w buforze zostaną w ten sposób utracone, ale w tym momencie ich nie ma)
Jakie są konsekwencje braku natychmiastowego zamknięcia pliku? W normalnych warunkach potencjalnie utracisz część danych i potencjalnie zabraknie deskryptorów plików. Ale jeśli masz system, w którym możesz tworzyć pliki, ale nie możesz nic do nich pisać, masz większy problem. tj. trudno sobie wyobrazić, dlaczego wielokrotnie próbujesz utworzyć ten plik, mimo że nie udaje Ci się.
Zarówno OutputStreamWriter, jak i BufferedWriter nie zgłaszają wyjątku IOException w swoich konstruktorach, więc nie jest jasne, jaki problem spowodowałby. W przypadku BufferedWriter możesz uzyskać OutOfMemoryError. W tym przypadku natychmiast uruchomi GC, który, jak widzieliśmy, i tak zamknie plik.