2009-03-22 6 views
5

Sto scrivendo un programma che esegue un processo secondario esterno in modo interattivo e ho bisogno del contenuto dell'handle di output per essere inviato a stdout non appena è disponibile . Ho provato qualcosa di simile:Haskell: Come convogliare i contenuti di un handle in un altro in tempo reale

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 

Ma questo non funziona in quanto riconosce solo linea di uscita per linea, in modo che qualsiasi uscita sul manico uscita processi che non termina con un ritorno a capo non si presenta . Ho provato la stessa cosa con hGetContents ma produce lo stesso risultato. Ho letto la documentazione di System.Process e System.IO e non ho trovato nulla di conclusivo.

risposta

4

hSetBuffering è quello che stai cercando, il default (su Unix almeno) è il buffering di linea. Usalo sul stdin prima di avviare il ciclo principale

hSetBuffering hIn NoBuffering 

ed eventualmente anche sulla maniglia di output se si desidera vedere i risultati immediatamente sul lato di uscita. Si noti, tuttavia, che la disattivazione del buffering può ridurre drasticamente le prestazioni.

+0

Grazie, non ho nemmeno pensato di cambiare la modalità di buffering su stdin/stdout. – drt

+0

Vale la pena notare che l'impostazione predefinita su Windows è diversa da quella predefinita su Linux, quindi vale comunque la pena impostare il tipo di buffer per ottenere un comportamento coerente. – porges

2

Sono un principiante di Haskell, ma ricordo di aver trovato un esempio recente di elaborazione dell'input carattere per carattere. hSetBuffering forse quello che stai cercando?

0

Il buffering è una cosa, ma si sta utilizzando anche gGetLine che attenderà un'intera riga (o la fine del file). Considerare l'utilizzo di hGetChar se si desidera veramente leggere un carattere alla volta. E btw, un altro modo per superare il buffering è usare hFlush.

Problemi correlati