2010-11-20 3 views
2

Javaでコマンドラインプログラムのターミナルラッパーを作成していますが、ProcessBuilderを使用してサブプロセスを生成しています。サブプロセスにキーストロークを送信するには、e.getKeyChar()をGUIから直接OutputStreamproc.getOutputStream())に書き込んでください。私はすぐに両方端に出力をフラッシュ場合Java:プロセスからstdoutデータを取得できません。手動でフラッシュしない限り

while ((b = br.read()) != -1) { 
    System.out.println("Read "+b); 
    bb[0] = (byte) b; 
    // call an event listener with the read byte 
    listener.dataReceived(bb); 
} 

これは動作しますが、のみ:サブプロセスからの出力を受け、私は基本的にサブプロセスのstdoutから読み込むwhileループを持っています。つまり、すべてのユーザー入力をフラッシュしなければならず、サブプロセスは自分自身をフラッシュする必要があります。stdoutそうでなければ、read()ブロック、実際には送信されないデータを待っています(サブプロセスのstdoutは単にバッファリングを続けます)。 I/Oはどのようにして入手できますか?

例の端末サブプロセスは:

#include <stdio.h> 

int main() { 
    char c; 
    while((c = getchar()) != -1) { 
     printf("Got: %d\n", c); 
     // doesn't work in my Java program if the next line isn't present 
     fflush(stdout); 
    } 
    return 0; 
} 

私は、データがディスクに書き込まれるまであなたはファイルからデータを読み取ることができないのSun Java 6

答えて

1

多くの多くのランタイムライブラリ(例えば、私はlibcのがこれを行うと、他の人があまりにもなければ、まったく驚かないことを知っている)の出力が端末にあるときを除き、デフォルトことによって、それらの出力をバッファリングします。これは、多くの行(例えば、通常のパイプライン)を扱うときのデータ処理の効率を非常に向上させるが、情報量が少ないときには多くのことを傷つける。サブプロセスのソースにアクセスできる場合は、バッファリングをオフにしたり、フラッシュを追加してコードを更新するのが最善の方法です。

しかし、これは必ずしも可能ではありませんが、特にサードパーティのコードを扱う場合はそうではありません。最高の私が知っている修正は、Expectのようなツールを使用してサブプロセスを欺くことです。内部的には、Expectはターミナル(UNIX上ではptysを使い、Windowsではgodawfulなハックを使う)をする方法を知っているので、他のプログラムを騙してバッファリングを止める(少なくとも減らす)ようにする。 Expectにはこのような使い方に焦点を合わせるためのスクリプト(アンバッファー)があります。 (一般的に、バッファリングを扱うこと以外にも多くのことを行うことができますが、とにかく最高の解決策です。)

4

でのUbuntu 10.10上で実行していますよ。 パイプまたはソケットのバッファにデータが格納されるまで、ソケットまたはパイプからデータを読み取ることはできません。

外部プロセスが出力をフラッシュしてデータをディスク/パイプバッファ/ソケットバッファに書き込むとき、Javaプログラムは制御(*)しません。あなたは完全に外部プログラムのバッファリング動作の慈悲に満ちています。これは、すべてのオペレーティングシステムおよびすべてのプログラミング言語で当てはまります。

すべてのネットワークプログラマはこれに対処しなければならないので、それに対処してください。

(*) - 場合によっては、プログラムにバッファリングされていない出力を使用するように指示するオプション(-u)があります(catなど)。それ以外の場合は、

+0

私のJavaプログラムでは、I/O * never *が送信されますが、手動でサブプロセスを端末で実行すると、I/Oはほぼ即座に実行されます。 – erjiang

+0

ええ、我々はそれに対処しなければならないことを知っている。問題はどういうことか。 – jononomo

0

のイベントのディスパッチスレッドからI/O読み取りループを実行していませんか?

サブプロセスからI/O読み取りを別のスレッドで実行する必要があります(まだ実行していない場合)。 GUIキープレスごとにサブプロセスへの即時フラッシュが最適です。あなたが何らかの種類の「一度に全行を読む」をサポートしたいのでない限り、

+0

これは私が現在やっていることです。私は別のスレッドをサブプロセスから読み込み( 'read()'ブロックから)、メインスレッドのイベントハンドラに通知します。キーストロークはすぐにサブプロセスに送信され、フラッシュされます。 – erjiang

関連する問題