Java 6 で継承された stdin/stdout/stderr を使用してプロセスを開始する
質問
Java経由でプロセスを開始した場合 プロセスビルダー クラスの場合、そのプロセスの標準入力、標準出力、および標準エラー ストリームに Java として完全にアクセスできます。 InputStreams
そして OutputStreams
. 。ただし、これらのストリームをシームレスに接続する方法が見つかりません。 System.in
, System.out
, 、 そして System.err
.
使用可能です redirectErrorStream()
シングルを手に入れるために InputStream
これにはサブプロセスの標準出力と標準エラーが含まれており、それをループして標準出力を通じて送信するだけです。しかし、それを実行して、ユーザーがプロセスに入力できるようにする方法が見つかりません。 Cを使用しました system()
電話。
Java SE 7 がリリースされると、これが可能になるようです。現在、回避策があるかどうか疑問に思っています。結果があればボーナスポイント isatty()
子プロセスではリダイレクトが実行されます。
解決
をコピーする必要があります。 プロセス out、err、およびシステム バージョンへの入力ストリーム。それを行う最も簡単な方法は、 IOUtils Commons IO パッケージのクラス。の コピー方法 必要なもののようです。copy メソッドの呼び出しは別のスレッドで行う必要があります。
基本的なコードは次のとおりです。
// Assume you already have a processBuilder all configured and ready to go
final Process process = processBuilder.start();
new Thread(new Runnable() {public void run() {
IOUtils.copy(process.getOutputStream(), System.out);
} } ).start();
new Thread(new Runnable() {public void run() {
IOUtils.copy(process.getErrorStream(), System.err);
} } ).start();
new Thread(new Runnable() {public void run() {
IOUtils.copy(System.in, process.getInputStream());
} } ).start();
他のヒント
John の回答のバリエーションで、コンパイルされ、Commons IO を使用する必要はありません。
private static void pipeOutput(Process process) {
pipe(process.getErrorStream(), System.err);
pipe(process.getInputStream(), System.out);
}
private static void pipe(final InputStream src, final PrintStream dest) {
new Thread(new Runnable() {
public void run() {
try {
byte[] buffer = new byte[1024];
for (int n = 0; n != -1; n = src.read(buffer)) {
dest.write(buffer, 0, n);
}
} catch (IOException e) { // just exit
}
}
}).start();
}
のために System.in
以下を使用します pipein()
の代わりに pipe()
pipein(System.in, p.getOutputStream());
実装:
private static void pipein(final InputStream src, final OutputStream dest) {
new Thread(new Runnable() {
public void run() {
try {
int ret = -1;
while ((ret = System.in.read()) != -1) {
dest.write(ret);
dest.flush();
}
} catch (IOException e) { // just exit
}
}
}).start();
}