Haskell: come pipe il contenuto di una maniglia in un altro in tempo reale
Domanda
Sto scrivendo un programma che viene eseguito un processo sub esterna in modo interattivo e ho bisogno il contenuto della maniglia di uscita per essere allo standard output non appena è disponibile. Ho provato qualcosa di simile:
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 riga, 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 attraverso la documentazione di entrambi System.Process e System.IO e non ho davvero trovato nulla conclusivo.
Soluzione
hSetBuffering
è quello che stai cercando, il default (su Unix, almeno) è la linea di buffering. 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 buffer può maniera drastica riduzione delle prestazioni.
Altri suggerimenti
Sono molto un novizio Haskell, ma mi ricordo di imbattersi in un esempio recente di elaborazione carattere carattere per input. E ' hSetBuffering forse quello che stai cercando?
Il buffering è una cosa, ma si utilizza anche gGetLine
che aspettare una intera linea (o alla fine del file). Considerare l'utilizzo di hGetChar
se si vuole veramente di leggere un carattere al tempo.
E a proposito, un altro modo di superare il buffer è di usare hFlush
.