2012-05-11 6 views
1

Javaの対話型プロセスに問題があります。 STDOUTとSTDERRを読み込むスレッドと、そのプロセスの入力を処理するスレッドがあります。ただし、プロセスが終了するまでは、STDOUTストリーム内で使用可能なデータはありません。次に、出力全体が一度に印刷されます。Java exec - プロセスが終了するまで対話型プロセスの出力が保持されます

DBG | Pipe action-STDERR started 
DBG | Pipe action-STDIN started 
DBG | Pipe action-STDOUT started 

STDIN | Try to put some input. 
STDIN | I cannot see any output. 
STDIN | Nevertheless the interaction works. 
STDIN | It works on background. 
STDIN | Let's terminate the process to see the truth. 
STDIN | quit 

STDOUT | Enter some text, please: The text is 'Try to put some input.' 
STDOUT | Enter some text, please: The text is 'I cannot see any output.' 
STDOUT | Enter some text, please: The text is 'Nevertheless the' 
STDOUT | Enter some text, please: The text is 'interaction works.' 
STDOUT | Enter some text, please: The text is 'It works on background.' 
STDOUT | Enter some text, please: The text is 'Let's terminate the process to see the truth.' 
STDOUT | Enter some text, please: The text is 'quit' 
STDOUT | Bye! 
DBG | Trying to kill thread action-STDOUT 
DBG | Trying to kill thread action-STDERR 
DBG | Trying to kill thread action-STDIN 
DBG | Pipe action-STDERR finished 
DBG | Finished 
DBG | Pipe action-STDIN finished 
DBG | Pipe action-STDOUT finished 

接頭辞がSTDOUTの行は、プロセスによって書き込まれた行です。接頭辞STDINの行は私が書いた行です。 DBGが先頭に付いている行は、テスト済みのJavaプログラムによってデバッグ情報として書き込まれた行です。システムコンソールで同じプロセスを実行しようとしましょう。

この動作は私の期待に応えます。私はいくつかの入力を求められています。私はそれをして答えを得る。

私は驚いています、私はStackoverflowを含むウェブ上のいくつかの投稿を見つけましたが、回答は受け入れられません。 (例えば、Problem reading InputStream from Java Process。)Java開発者は対話型プロセスの実行を扱っていないようです。奇妙なことは、プロセスが実行されている間に、非対話型プロセス(pingなど)の出力が順番に現れることです。問題なし。しかし、プロセスがユーザーの入力を待っているとき、出力は何とかブロックされます。

+0

書き込まれる他のプロセス(「サーバー」)とは何ですか?毎回標準出力をフラッシュするようにしていますか? –

+0

おそらくそうではありませんが、プロセスはこのレベルのブラックボックスです。私はそれに影響を与えることができないので、出力をフラッシュするかどうかは関係ありません。 Javaコード内の問題を解決する必要があります。 –

答えて

1

残念ながら、それはバグではなく、機能です。 LinuxまたはWindowsのいずれかのパイプは、このように実装されています。パフォーマンスを向上させるためにバッファリングされています。 1つのプロセスがデータを生成し、2つ目のプロセスがデータを生成します。対話は必要ありません。このモデルは99%のケースでも機能します。

しかし、コンソールは別の種類のアプリケーションです。システムコンソールはOSの一部であり、私たちのコンソールがJavaで書かれたやり方と少し違って動作します。もちろん、システムコンソールはすべてのデータをすぐに印刷します。すべて正常に動作します。それで、コードから実行されたのと同じプロセスではプロンプトが表示されません。どうしましたか?システムコンソールとプロセスの間にバッファはありません。しかし、逆に、私たちのプロセスとJavaコードの間にバッファーがあります。それが原因です。

プロセスは自動的に出力をフラッシュしません。プロセスが記述されている言語にかかわらず、Java、Perl、またはCで書かれたプロセスは、コードに明示的なフラッシュが追加されるまでプロンプトを表示しません。あなたがと相互作用するプロセスのコードに影響を与えることができれば、(擬似コードは以下の)コードを更新:

print 'Give me a number ' 
flush STDOUT 
number = get STDIN 
print 'You wrote ' + number 
flush STDOUT 

別の解決策はありません。サードパーティアプリケーションが出力をフラッシュしない場合は、コンソールで使用することはできません。あなたはほとんどバッファリングを回避することはできません。それにもかかわらず、何とか可能です。ライブラリがあるか、問題のあるプロセスとやり取りしてそのコードを調べることができるオープンソースのアプリケーションを見つけることができます。

ヒント:チェックアウトApache Commons Execこれは、プロセス実行に特化したライブラリです。

関連する問題