こんにちは。システムエンジニアの篠原です。
先日、Javaで開発したプログラムにいただけないミスをしてしまったため、自戒のためにも記載します。
JavaにおいてFileオブジェクトを取り扱う場合、読み込みの際には BufferedReader クラス等を使用することになると思います。
こうしたクラスはJava1.7以降 AutoClosable インターフェースを実装しており、try-with-resource 構文を使うことで、ブロックを抜けた際に自動的に閉じることができます。
とても便利ですね。
try (BufferedReader br = new BufferedReader(new FileReader("hoge.txt"))) { System.out.println(br.readLine()); }
Eclipseで開発をしている場合、BufferedReader.read() メソッドを記述すると、IOExceptionをスローする旨のコンパイルエラーが表示されますが、今回、私はここでうっかり、try-catchで囲む自動補完を行っただけで満足してしまったのです。
try { BufferedReader br = new BufferedReader(new FileReader("hoge.txt")); System.out.println(br.readLine()); } catch (IOException e) { log.error(e.getMessage(), e); }
こうしてしまうと、BufferedReaderクラスのcloseメソッドが呼ばれることはありません。
大量のファイル処理を行うと、たちまちサーバーのファイルディスクリプタが枯渇して、ファイルが開けなくなります。
本当はファイルが閉じられないことを示す警告が出れば一番よいのですが、現状のEclipseではうまくはたらかない模様…
ソースレビュー観点に入れ、確実に見落とさないようにすることの大切さを実感しました。
また可能であれば、Apache Commonsや各種フレームワークで用意されているファイルユーティリティークラスを使用したり、共通のUtilクラスを作成するなどして、閉じ忘れの失念を防ぐ工夫をすることをお勧めします。