2009-03-22 19 views
5

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

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 и на самом деле не нашел ничего убедительного.

ответ

4

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

hSetBuffering hIn NoBuffering 

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

+0

Спасибо, я даже не думал об изменении режима буферизации на stdin/stdout. – drt

+0

Стоит отметить, что значение по умолчанию для Windows отличается от стандартного по умолчанию в Linux, поэтому в любом случае стоит настроить тип буферизации, чтобы получить согласованное поведение. – porges

2

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

0

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