0

Javaから外部プロセスを生成し、その入力に定期的に書き込み、コンソールであるかのように応答を読み取ることができるようにしたいと思います。ただし、多くの場合、プロセスの出力を読み取ると、何も利用できません。この種のことを(それを避けても)行うための良い習慣はありますか?

これは、機能しないものの簡略化された例です。

import org.apache.commons.exec.*;
import java.io.*;
//...
CommandLine cl = CommandLine.parse("/usr/bin/awk {print($1-1)}");
System.out.println(cl.toStrings());
Process proc = new ProcessBuilder(cl.toStrings()).start();
OutputStream os = proc.getOutputStream(); // avoiding *Buffered* classes
InputStream is = proc.getInputStream();   // to lessen buffering complications
os.write(("4" + System.getProperty("line.separator")).getBytes());
os.flush(); // Doesn't seem to flush.
// os.close(); // uncommenting works, but I'd like to keep the process running
System.out.println("reading");
System.out.println(is.read()); // read even one byte? usually is.available() -> 0

不思議なことに、OutputStreamをBufferedWriterでラップすると、一部のプロセス(cat)からは読み取ることができますが、他のプロセス(awk、grep)からは読み取ることができません。

4

1 に答える 1

1

一般的に、採用されたアプローチは適切です。ただし、いくつかのこと:

  1. InputStream.read()ブロッキング方法です。入力を待機し、CPU を集中的に使用しません。あなたはそれを中心に回るべきです...
  2. 複数のバイトを読み取ることができます。使用するだけですread(byte[] buffer, int offset, int len)
  3. 入力ストリームを BufferedInputStream にラップすると、アクセスが容易になります (readLine()メソッド)。これは BufferedReader の代替です。
  4. を使用することを忘れないでくださいProcess.waitFor()

また、外部プロセスが (標準エラーではなく) 標準出力に書き込むことを確認してください。ここで 2 つの可能性:

  1. 使用するProcess.getErrorStream()(そしてそれを別の InputStream として扱う)
  2. コマンド ラインを に変更します。これにより、標準エラーが標準出力にリダイレクトされます。/usr/bin/awk {print($1-1)} 2>&1
于 2012-10-31T15:06:48.630 に答える