I'm wrapping the FM-SBLEX Saldo program in a Java library.
Saldo is written in Haskell and does lookups in a lexicon for lines given on stdin, e.g.
echo "ord"|./sblex/bin/saldo dicts/saldo.dict
prints something like the following to stdout
{"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"},...
If I run it with
./sblex/bin/saldo dicts/saldo.dict
it does a lookup for each line I enter at the console until I send EOF.
In my Java library, I start it with ProcessBuilder and set up a thread to dump stdout and stderr to my program's stdout, and another thread writes a word and a newline, then flushes outputStream
On the console, saldo returns results each time I press return, but in my wrapper, it returns results for all my input only once I close outputStream (see .close() is commented out in the next code block)
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);
Writer's run override:
public void run() {
try {
outputStream.write("ord\n".getBytes());
outputStream.flush();
//outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
The Haskell code that reads the input
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
If binPath="cat" and dictPath="-" my java program outputs the input after each flush. Any idea why this haskell program is only dealing with the input after I close the outputStream?
NB: as the answer shows, it was not hGetLine that didn't return (as I assumed) but the output that was buffered because the Haskell implementation I'm using defaults to block buffer if it's not run from the console.