2012-03-31 72 views
3

我將FM-SBLEX Saldo程序包裝在Java庫中。使用Java ProcessBuilder運行haskell可執行文件:爲什麼只有在關閉outputStream時hGetLine纔會返回?

Saldo是用Haskell編寫的,並在詞典的詞典中查找,例如,

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查找運行它。

在我的Java庫,我的ProcessBuilder啓動它,併成立了一個線程轉儲輸出和錯誤,以我的程序的標準輸出,而另一個線程寫入一個字和一個換行符,然後刷新的OutputStream

在控制檯上, saldo返回結果中的每個我按返回時間,但在我的包裝,它返回我的所有輸入只有一次我收的OutputStream(見.close()中的一個代碼塊是註釋掉)

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(); 
     } 
    } 

的Haskell代碼讀取輸入

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 

如果binPath = 「貓」 和DICTPATH = 「 - 」 我的java程序輸出每次沖洗後的輸入。任何想法爲什麼這個haskell程序只是在關閉outputStream後處理輸入?

注意:正如答案所示,不是hGetLine沒有返回(正如我所設想的那樣),而是因爲我使用的Haskell實現使用默認的緩衝區,所以緩衝的輸出如果不是從安慰。

回答

4

您的Haskell程序可能會緩衝其輸出。 (當它寫入到終端行緩衝,塊緩衝寫入任何東西的時候。)

嘗試增加

hSetBuffering stdout LineBuffering 

節目開始不久。

More about buffering in Haskell.

(編輯響應于丹尼爾瓦格納的註釋。)

+2

如果輸入的一行對應於輸出中的至少一個的行,然後'LineBuffering'可能是更合適的。 – 2012-03-31 15:42:54

+0

修復它的代碼工作,但是你知道一種讓程序認爲它是從控制檯運行(而不是更改第三方代碼)的方法嗎?我看到有人建議在'script/dev/null'下運行它,但是我想知道Java是否支持更平臺無關的方式? – jbothma 2012-03-31 15:52:44

+0

我不知道如何使用Java,但如果你在Linux/OSX /其他Unix上運行,並且已經安裝了腳本程序,你可以讓Java運行腳本-c。/sblex/bin/saldo dicts/saldo.dict「/ dev/null」而不是'./sblex/bin/saldo dicts/saldo.dict'。 – dave4420 2012-03-31 16:24:59

相關問題