2012-03-31 6 views
3

私はFM-SBLEX SaldoプログラムをJavaライブラリにラッピングしています。Java ProcessBuilderを使用してhaskellを実行する:hGetLineはなぜoutputStreamを閉じると返されますか?

SaldoはHaskellで書かれており、stdinに与えられた行のレキシコンでルックアップします。

echo "ord"|./sblex/bin/saldo dicts/saldo.dict 

プリント

{"ord":{"s_1":{"word":"ord","head":"sanna mina ord","pos":"abm","param":"invar 1:3-3","inhs":[],"id":"sanna_mina_ord..abm.1","p":"abm_i_till_exempel","attr":"3"},... 

私は

./sblex/bin/saldo dicts/saldo.dict 

でそれを実行した場合、私はEOFを送信するまで、それは私が、コンソールで入力した各行のルックアップを行うにstdoutに以下のようなものを。私のJavaライブラリで

、私はProcessBuilderをとそれを開始し、私のプログラムの標準出力をstdoutとstderrをダンプするためのスレッドを設定し、別のスレッドが単語と改行を書き込み、その後、コンソールで

をOutputStreamのフラッシュsaldoは結果に私がリターンを押すたびに返しますが、私のラッパーで、それは私が(次のコードブロックではコメントアウトされている。.closeを(参照))のOutputStream閉じるだけ一度私のすべての入力

ProcessBuilder pb = new ProcessBuilder(binPath, dictPath); 

    pb.redirectErrorStream(true); 
    saldoProcess = pb.start(); 

    new Thread(new Reader(saldoProcess.getInputStream())).start(); 
    new Thread(new Writer(saldoProcess.getOutputStream())).start(); 

    saldoProcess.waitFor(); 
    System.out.println("saldo exited."); 
    Thread.sleep(2000); 

ライターの実行の結果を返します。上書き:

public void run() { 
     try { 
      outputStream.write("ord\n".getBytes()); 
      outputStream.flush(); 
      //outputStream.close(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

BINPATH = "猫" とDICTPATH =が場合は入力

run' :: Language a => a -> (String -> [Tok]) -> (String -> [[String]]) -> AnaType -> Stats -> IO Stats 
run' l tokenizer f a st = 
do b <- hIsEOF stdin 
    if b then return st 
    else do 
     s <- hGetLine stdin 
     analyze l a f (tokenizer s) st >>= run' l tokenizer f a 

を読み込みHaskellコード " - " 私のJavaプログラムは、各フラッシュの後に入力して出力します。私はoutputStreamを閉じた後、このhaskellプログラムが入力を扱うのはなぜですか?

NB:答えとして、返されなかったhGetLine(私が想定したように)ではなく、Haskell実装のためにバッファリングされた出力です。コンソール。

答えて

4

あなたのHaskellプログラムはおそらくその出力をバッファしています。プログラムの開始の近く

hSetBuffering stdout LineBuffering 

を追加する(ラインバッファリングされ、それは、端末への書き込みだとき、ブロック・バッファ何か他のものへの書き込み。)

してみてください。

More about buffering in Haskell.

(ダニエル・ワグナーさんのコメントに応じて編集しました。)

+2

入力の1行が出力の少なくとも一つの行に対応している場合、 'LineBuffering'はおそらくより適切です。 –

+0

コード内で修正することはできますが、サードパーティのコードを変更する代わりに、コンソールからプログラムが実行されていると思うようにする方法を知っていますか?誰かが 'script/dev/null'の下で実行することを勧めているのを見たことがありますが、Javaがプラットフォームに依存しないこれを行う方法をサポートしているのだろうか? – jbothma

+0

Javaのやり方についてはわかりませんが、Linux/OSX /その他のUnix上で実行していて、 'script'プログラムがインストールされていれば、Javaに' script -c 'を実行させることができます。 './sblex/bin/saldo dicts/saldo.dict'の代わりに/ sblex/bin/saldo dicts/saldo.dict"/dev/null'を実行してください。 – dave4420

関連する問題