1

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

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プログラムによってデバッグ情報として書き込まれた行です。システムコンソールで同じプロセスを実行してみましょう。

Enter some text, please: Text
The text is 'Text'
Enter some text, please: quit
The text is 'quit'
Bye!

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

Stackoverflowを含むいくつかの投稿をウェブ上で見つけたのに驚いていますが、許容できる解決策としてマークされた回答はありません。(たとえば、JavaプロセスからのInputStreamの読み取りの問題。)Java開発者は、対話型プロセスの実行を扱ったことがないようです。奇妙なことに、プロセスの実行中に、非対話型プロセスの出力(pingとして)が順番に表示されます。問題ありません。ただし、プロセスがユーザー入力を待機している場合、出力は何らかの理由でブロックされます。

4

1 に答える 1

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を調べてください。プロセス実行に特化したライブラリです。

于 2012-07-09T07:15:47.440 に答える