0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Jython】AutoCloseable / Closeable 実装オブジェクトに with 文を使うには

Last updated at Posted at 2022-01-11

try-with-resources文とwith

Java にはtry-with-resourcesがあり、これを、インターフェースAutoCloseable又はインタフェースCloseableを実装したクラスをインスタンス化したオブジェクト(以下、AutoCloseable/ Closeable実装オブジェクト)が使用すると、ブロック終了時又は例外発生時に於いて、自動的にそのオブジェクトのclose()メソッドが呼び出され、クローズ処理が為される。

次に示すJavaソースコードファイルMain.javaには、2 つのtry-with-resources文があり、変数bw及び変数brに、AutoCloseable/ Closeable実装オブジェクトの参照が格納されている。

Main.java
// -*- 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メソッド1Jython (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を、次に示す。

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
いろはにほへと ちりぬるを
わかよたれそ つねならむ
うゐのおくやま けふこえて
あさきゆめみし ゑひもせす

参考

  1. 但し、Closeable未実装のAutoCloseable実装オブジェクトをuseメソッドに対応させるには、kotlin-stdlib-jdk7.jarをクラスパスに追加しなければならない。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?