今回はパイプストリームについて紹介したいと思います。
他のブログやAPIリファレンスに書いてある通り、プログラムの出力結果をパイプします。
Linuxコマンドのパイプのように、あるプログラムの出力結果を別のプログラムの入力としたいときに使用します。
実際にJavaプログラム間でデータのやり取りをするとき、データオブジェクトを介して行います。データオブジェクトにデータを格納したほうがデバッグでデータを簡単に参照できて利便性がよいため、パイプを使う場面はあまりありません。
それをあえてパイプを使うのは、何らかの制約があるためです。
例えば、PrintWriterで結果を出力するAPIを使うときです。
このようなときは、APIを修正するわけにもいかないため(APIをメンテナンスするのなら修正してもよいと思いますが)、PrintWriterからパイプして、後続プログラムに結果を渡します。
★バッファサイズ
一度読み込んだデータはパイプ内に保管されます。
パイプ内で保管できる容量は限度があり、コンストラクタで指定できます。
(ただし、Java5ではバッファサイズは1024byteで変更不可)
APIリファレンスに書いていませんが、バッファサイズに到達するとデータを読み出すまで、無限ループをします。
バッファサイズはメッセージのサイズによって決めるのが望ましいです。
ただ、メッセージのサイズが決まっていない場合はバッファサイズを超えることがあります。
その場合は非同期でデータを読み出す必要があります。前段のプログラムが終わるまでデータオブジェクトに逐次格納するか、後続のプログラムを非同期で実行してしまうなどの策が考えられます。
例.ECJ(Eclipse Compiler for Java)のコンパイル結果(ワーニング、エラー)をパイプする
※見やすくするため、コードを一部省略しています。
PipedReader pr = new PipedReader(pw);
// PrintWriterにPipedWriterをセット
PrintWriter print = new PrintWriter(pw);
// APIにPrintWriterを渡す
BatchCompiler.compile(
new String[]{"none"},
print,
print,
null
);
pw.close();
StringBuffer msg = new StringBuffer();
if (pr.ready()) {
char[] cbuf = new char[1024];
// 出力メッセージをパイプから取り出して、msgに格納する
pr.read(cbuf, 0, 1024);
msg.append(new String(cbuf).trim());
}
http://www1.megaegg.ne.jp/~yasu/Programmer's%20Page/stream/PipedStream.html
