2009-03-22 13 views
5

Estoy escribiendo un programa que ejecuta un subproceso externo de forma interactiva y necesito que el contenido del manejador de salida salga a stdout tan pronto como esté disponible . He intentado algo como esto:Haskell: Cómo pasar el contenido de un manejador a otro en tiempo real

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 

Pero esto no funciona, ya que sólo reconoce la línea de salida por línea, por lo que cualquier salida en el mango de salida procesos que no está terminada por un salto de línea no aparece . He intentado lo mismo con hGetContents pero produce el mismo resultado. He leído la documentación de System.Process y System.IO y realmente no he encontrado nada concluyente.

Respuesta

4

hSetBuffering es lo que está buscando, el valor predeterminado (en Unix al menos) es el almacenamiento en línea de la memoria intermedia. Usarlo en la entrada estándar antes de empezar el bucle principal

hSetBuffering hIn NoBuffering 

y opcionalmente también en el mango de salida si desea ver los resultados inmediatamente en el lado de salida. Tenga en cuenta, sin embargo, que deshabilitar el almacenamiento en búfer puede disminuir drásticamente el rendimiento.

+0

Gracias, ni siquiera pensé en cambiar el modo de almacenamiento en búfer en stdin/stdout. – drt

+0

Vale la pena señalar que el valor predeterminado en Windows es diferente al predeterminado en Linux, por lo que vale la pena establecer el tipo de almacenamiento en búfer de todos modos para obtener un comportamiento consistente. – porges

2

Soy muy novato en Haskell, pero recuerdo haber encontrado recientemente un ejemplo de procesamiento de entrada carácter por carácter. ¿Es hSetBuffering posiblemente lo que estás buscando?

0

El almacenamiento en búfer es una cosa, pero también está utilizando gGetLine, que esperará toda una línea (o hasta el final del archivo). Considere usar hGetChar si realmente desea leer un carácter a la vez. Y, por cierto, otra forma de superar el almacenamiento en búfer es usar hFlush.

Cuestiones relacionadas