尝试通过使用Java代码在Haskell中运行简单的脚本。 (Windows 10)
haskell脚本如下:
import Data.Char(toUpper)
main = interact (map toUpper)
我用ghc制作了一个simple.exe文件,它可以从cmd模块按预期工作。我写了一个简单的字符串,并用大写字母答复了相同的字符串,我可以重复此操作,直到选择停止程序为止。
但是当我尝试通过Java运行该程序时,它将无法正常运行。我可以提供输入,但是为了获得输出,我需要关闭输入提要。
public class Main {
public static void main(String[] args) {
try {
Process process = new ProcessBuilder("simple").start();
InputStream processInputStream = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(processInputStream));
OutputStream processOutputStream = process.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(processOutputStream));
char[] bt = ("Hello").toCharArray();
writer.write(bt);
writer.flush();
writer.newLine();
processOutputStream.close(); -- Only works if I close output stream,.
System.out.println(reader.readLine());
}catch (IOException e) {
e.printStackTrace();
}
}
}
如何在不关闭Java程序中的输出提要的情况下获得输出。
重新启动该过程是可行的,但是执行时间太长了。
我尝试对程序进行线程化,结果相同。
答案 0 :(得分:2)
BufferedWriter
在执行newLine()
时不会自动刷新其输出。因此,您的Haskell程序将不会收到换行符并永远等待。
调用close()
时,所有剩余的缓冲输出都将被刷新(但是,当然,您不想这样做)。
因此解决方案应该是
writer.write(bt);
writer.newLine();
writer.flush();
您还可以使用PrintWriter
,它具有自动换行刷新选项并且可以理解字符串(通过print
方法),因此无需弄乱char[]
。
最后,如果您打算同时发送或发送大量文本,则当程序无法再发送输出时,由于接收Java代码,您可能必须调整缓冲区大小或使用多个线程来避免死锁。侧缓冲区已满,您目前尚未读出。有关解决方案,请参见此thread。
答案 1 :(得分:1)
我做了一些实验,我需要在Haskell端进行行缓冲,否则输出不会及时刷新。
import Data.Char(toUpper)
import System.IO
main = do
hSetBuffering stdout LineBuffering
interact (map toUpper)
实际上,我发现从Java调用stdout
时最初将其设置为BlockBuffering
,这会缓冲太多。
请注意,正如Thilo所指出的,为了在Haskell端使用LineBuffering
,必须先在Java端使用writer.newLine()
,然后刷新(em ),否则大写输出将不会被刷新(在Haskell中)。