try-with-resources
文とwith
文
Java にはtry-with-resources
文があり、これを、インターフェースAutoCloseable
又はインタフェースCloseable
を実装したクラスをインスタンス化したオブジェクト(以下、AutoCloseable
/ Closeable
実装オブジェクト)が使用すると、ブロック終了時又は例外発生時に於いて、自動的にそのオブジェクトのclose()
メソッドが呼び出され、クローズ処理が為される。
次に示すJavaソースコードファイルMain.java
には、2 つのtry-with-resources
文があり、変数bw
及び変数br
に、AutoCloseable
/ Closeable
実装オブジェクトの参照が格納されている。
// -*- coding: utf-8; -*-
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
class Main {
public static void main(String[] args) {
final File file = new File("iroha.txt");
// ファイル書き込み
try (final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {
bw.write("いろはにほへと ちりぬるを");
bw.newLine();
bw.write("わかよたれそ つねならむ");
bw.newLine();
bw.write("うゐのおくやま けふこえて");
bw.newLine();
bw.write("あさきゆめみし ゑひもせす");
bw.newLine();
} catch (IOException e) {
e.printStackTrace();
}
// ファイル読み込み
try (final BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
次に、Java コンパイラのバージョン確認、ソースコードのコンパイル、及び実行例を示す。
$ javac -version
javac 17.0.1
$ javac -encoding UTF-8 Main.java
$ java Main
いろはにほへと ちりぬるを
わかよたれそ つねならむ
うゐのおくやま けふこえて
あさきゆめみし ゑひもせす
多くのJVM言語は、Java のtry-with-resources
文に相当する機能を備えている。例えば、Kotlin のuse
メソッド1、Jython (Javaで記述されたPython処理系) のwith
文が挙げられる。
もし、Main.java
を Jython スクリプトに移植しようとするなら、だいたい次のようなものを想像するだろう。
# -*- coding: utf-8; -*-
from java.io import BufferedReader, BufferedWriter, File, FileInputStream, FileOutputStream, InputStreamReader, OutputStreamWriter
from java.nio.charset import StandardCharsets
file = File(u"iroha.txt")
# ファイル書き込み
with BufferedWriter(OutputStreamWriter(FileOutputStream(file), StandardCharsets.UTF_8)) as bw:
bw.write(u"いろはにほへと ちりぬるを")
bw.newLine()
bw.write(u"わかよたれそ つねならむ")
bw.newLine()
bw.write(u"うゐのおくやま けふこえて")
bw.newLine()
bw.write(u"あさきゆめみし ゑひもせす")
bw.newLine()
# ファイル読み込み
with BufferedReader(InputStreamReader(FileInputStream(file), StandardCharsets.UTF_8)) as br:
line = br.readLine()
while line:
print(line)
line = br.readLine()
しかし、上記スクリプトは動作せず、次のエラー文を印字する。
AttributeError: 'java.io.BufferedWriter' object has no attribute '__exit__'
Jython は、他のJVM言語とは異なり、AutoCloseable
/ Closeable
実装オブジェクトであろうと関係なく、上記エラー文の指摘にもある実装要件を満たしていなければ、with
文を使うことはできない。
しかしながら、AutoCloseable
/Closeable
実装オブジェクトにwith
文を使う方法はある。
AutoCloseable
/Closeable
実装オブジェクトにwith
文を使うには
とっても簡単である。標準ライブラリのcontextlib.closing
関数を作用させれば良い。具体的には、上記スクリプトを次のように修正する。
# -*- coding: utf-8; -*-
+ from contextlib import closing
from java.io import BufferedReader, BufferedWriter, File, FileInputStream, FileOutputStream, InputStreamReader, OutputStreamWriter
from java.nio.charset import StandardCharsets
file = File(u"iroha.txt")
# ファイル書き込み
- with BufferedWriter(OutputStreamWriter(FileOutputStream(file), StandardCharsets.UTF_8)) as bw:
+ with closing(BufferedWriter(OutputStreamWriter(FileOutputStream(file), StandardCharsets.UTF_8))) as bw:
bw.write(u"いろはにほへと ちりぬるを")
bw.newLine()
bw.write(u"わかよたれそ つねならむ")
bw.newLine()
bw.write(u"うゐのおくやま けふこえて")
bw.newLine()
bw.write(u"あさきゆめみし ゑひもせす")
bw.newLine()
# ファイル読み込み
- with BufferedReader(InputStreamReader(FileInputStream(file), StandardCharsets.UTF_8)) as br:
+ with closing(BufferedReader(InputStreamReader(FileInputStream(file), StandardCharsets.UTF_8))) as br:
line = br.readLine()
while line:
print(line)
line = br.readLine()
修正済み Jython スクリプトファイルMain.py
を、次に示す。
# -*- coding: utf-8; -*-
from contextlib import closing
from java.io import BufferedReader, BufferedWriter, File, FileInputStream, FileOutputStream, InputStreamReader, OutputStreamWriter
from java.nio.charset import StandardCharsets
file = File(u"iroha.txt")
# ファイル書き込み
with closing(BufferedWriter(OutputStreamWriter(FileOutputStream(file), StandardCharsets.UTF_8))) as bw:
bw.write(u"いろはにほへと ちりぬるを")
bw.newLine()
bw.write(u"わかよたれそ つねならむ")
bw.newLine()
bw.write(u"うゐのおくやま けふこえて")
bw.newLine()
bw.write(u"あさきゆめみし ゑひもせす")
bw.newLine()
# ファイル読み込み
with closing(BufferedReader(InputStreamReader(FileInputStream(file), StandardCharsets.UTF_8))) as br:
line = br.readLine()
while line:
print(line)
line = br.readLine()
次に、Jython のバージョン確認、及び実行例を示す。
$ jython --version
Jython 2.7.2
$ jython Main.py
いろはにほへと ちりぬるを
わかよたれそ つねならむ
うゐのおくやま けふこえて
あさきゆめみし ゑひもせす
参考
-
但し、
Closeable
未実装のAutoCloseable
実装オブジェクトをuse
メソッドに対応させるには、kotlin-stdlib-jdk7.jar
をクラスパスに追加しなければならない。 ↩