Haskell: Как передать содержимое одной ручки в другую в режиме реального времени - PullRequest
5 голосов
/ 23 марта 2009

Я пишу программу, которая запускает внешний подпроцесс в интерактивном режиме, и мне нужно, чтобы содержимое дескриптора вывода было выведено на стандартный вывод, как только он станет доступен. Я пробовал что-то вроде этого:

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 голосов
/ 24 марта 2009

hSetBuffering - это то, что вы ищете, по умолчанию (по крайней мере в Unix) используется буферизация строки. Используйте его на stdin перед запуском основного цикла

hSetBuffering hIn NoBuffering

и, опционально, также на дескрипторе вывода, если вы хотите видеть результаты непосредственно на стороне вывода. Однако обратите внимание, что отключение буферизации может значительно снизить производительность.

2 голосов
/ 23 марта 2009

Я очень новичок в Haskell, но я помню, что недавно наткнулся на пример обработки ввода за символом. hSetBuffering - это то, что вы ищете?

0 голосов
/ 25 октября 2017

Буферизация - это одно, но вы также используете gGetLine, который будет ожидать целую строку (или конец файла). Попробуйте использовать hGetChar, если вы действительно хотите прочитать один символ за раз. И, кстати, еще один способ преодоления буферизации - использовать hFlush.

...