Haskell:如何将一个句柄的内容实时传输到另一个句柄中

5

我正在编写一个运行外部子进程的程序,并且需要在输出句柄可用时将其内容输出到标准输出。我尝试过类似以下的代码:

main = do processInfo <- createProcess (proc "ghci" []){std_out = CreatePipe,
                                                    std_in  = CreatePipe }
       case processInfo of
          (Just hIn, Just hOut, _, _) -> do mainloop hIn hOut
                                          hClose hIn
                                          hClose hOut
       _                              -> do error "Unable to start process"

mainloop :: Handle -> Handle -> IO ()
mainloop inh outh = 
    do ineof <- hIsEOF outh
       if ineof
          then return ()
          else do inpStr <- hGetLine outh
                  putStrLn inpStr
                  mainloop inh outh

但是这种方法不起作用,因为它只逐行识别输出,所以任何没有以换行符结尾的进程输出句柄上的输出都不会显示出来。我已经尝试使用hGetContents进行相同的操作,但结果相同。我已经阅读了System.Process和System.IO的文档,但并没有找到什么确定性的东西。

3个回答

4

hSetBuffering 是你需要寻找的函数,它的默认缓冲方式(至少在 Unix 上)是行缓冲。在进入主循环之前,对标准输入使用该函数。

hSetBuffering hIn NoBuffering

如果您想立即在输出端看到结果,可以选择在输出句柄上禁用缓冲。请注意,禁用缓冲可能会严重降低性能。


谢谢,我甚至没有想到要更改stdin/stdout的缓冲模式。 - drt
值得注意的是,在Windows上的默认设置与Linux上的默认设置不同,因此无论如何都值得设置缓冲类型以获得一致的行为。 - porges

2

我是一个Haskell新手,但最近我记得遇到过一个处理逐字节输入的例子。是否hSetBuffering 是你要找的东西?


0

缓冲是一回事,但您还在使用gGetLine,它将等待整行(或文件结尾)。如果您真的想一次读取一个字符,请考虑使用hGetChar。 另外,克服缓冲的另一种方法是使用hFlush


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接