我將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實現使用默認的緩衝區,所以緩衝的輸出如果不是從安慰。
如果輸入的一行對應於輸出中的至少一個的行,然後'LineBuffering'可能是更合適的。 – 2012-03-31 15:42:54
修復它的代碼工作,但是你知道一種讓程序認爲它是從控制檯運行(而不是更改第三方代碼)的方法嗎?我看到有人建議在'script/dev/null'下運行它,但是我想知道Java是否支持更平臺無關的方式? – jbothma 2012-03-31 15:52:44
我不知道如何使用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