最も外側のストリームを閉じることができます。実際には、すべてのストリームをラップして保持する必要はなく、Java 7のtry-with-resourcesを使用できます。
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new GZIPOutputStream(new FileOutputStream(createdFile)))) {
// write to the buffered writer
}
YAGNIまたはyou-aint-gonna-need-itを購読している場合は、実際に必要なコードのみを追加する必要があります。必要と思われるコードを追加するべきではありませんが、実際には何も有用ではありません。
この例を見て、これを実行しなかった場合に何が問題になる可能性があり、どのような影響があるかを想像してみてください。
try (
OutputStream outputStream = new FileOutputStream(createdFile);
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
OutputStreamWriter osw = new OutputStreamWriter(gzipOutputStream);
BufferedWriter bw = new BufferedWriter(osw)
) {
// ...
}
open
実際の作業をすべて実行するために呼び出すFileOutputStreamから始めましょう。
/**
* 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;
ファイルが見つからない場合、閉じる基礎となるリソースがないため、ファイルを閉じても違いはありません。ファイルが存在する場合は、FileNotFoundExceptionをスローする必要があります。したがって、この行だけからリソースを閉じようとしても、何も得られません。
ファイルを閉じる必要があるのは、ファイルが正常に開かれたときですが、後でエラーが発生します。
次のストリームを見てみましょう GZIPOutputStream
例外をスローできるコードがあります
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)
});
}
これにより、ファイルのヘッダーが書き込まれます。これで、書き込み用にファイルを開くことができても、8バイトも書き込むことができないのは非常に珍しいことですが、これが発生する可能性があり、後でファイルを閉じないことを想像してみてください。ファイルを閉じないとどうなりますか?
フラッシュされていない書き込みは取得されず、破棄されます。この場合、この時点ではバッファリングされていないストリームに正常に書き込まれたバイトはありません。しかし、閉じられていないファイルは永遠に生きるわけではなく、代わりに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();
}
}
}
ファイルをまったく閉じない場合は、すぐにではなく、とにかく閉じられます(前述のように、バッファーに残っているデータはこの方法で失われますが、現時点ではありません)。
ファイルをすぐに閉じないとどうなりますか?通常の状態では、一部のデータが失われる可能性があり、ファイル記述子が不足する可能性があります。しかし、ファイルを作成できるシステムにファイルを書き込むことができないシステムがある場合、より大きな問題が発生します。つまり、失敗しているにもかかわらずこのファイルを繰り返し作成しようとしている理由を想像するのは困難です。
OutputStreamWriterとBufferedWriterはどちらもコンストラクタでIOExceptionをスローしないため、どのような問題が発生するかは明確ではありません。BufferedWriterの場合、OutOfMemoryErrorが発生する可能性があります。この場合、GCがすぐにトリガーされます。これまで見てきたように、とにかくファイルを閉じます。