5 Stimmen

Haskell: Wie man den Inhalt eines Handles in ein anderes in Echtzeit leitet

Ich schreibe ein Programm, das einen externen Subprozess interaktiv ausführt, und ich muss den Inhalt des Ausgabe-Handles nach stdout ausgeben, sobald er verfügbar ist. Ich habe etwas Ähnliches versucht:

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

Aber das funktioniert nicht, da es die Ausgabe nur zeilenweise erkennt, so dass jede Ausgabe auf dem Ausgabe-Handle des Prozesses, die nicht durch einen Zeilenumbruch beendet wird, nicht angezeigt wird. Ich habe dasselbe mit hGetContents versucht, aber das Ergebnis ist dasselbe. Ich habe die Dokumentation sowohl von System.Process als auch von System.IO durchgelesen und nicht wirklich etwas Schlüssiges gefunden.

4voto

nominolo Punkte 5025

hSetBuffering ist das, wonach Sie suchen, der Standard (zumindest unter Unix) ist Zeilenpufferung. Verwenden Sie es auf stdin, bevor Sie die Hauptschleife starten

hSetBuffering hIn NoBuffering

und optional auch auf dem Ausgabe-Handle, wenn Sie die Ergebnisse sofort auf der Ausgabeseite sehen wollen. Beachten Sie jedoch, dass die Deaktivierung der Pufferung die Leistung ziemlich drastisch verringern kann.

0 Stimmen

Danke, ich habe gar nicht daran gedacht, den Pufferungsmodus für stdin/stdout zu ändern.

0 Stimmen

Es ist erwähnenswert, dass sich die Standardeinstellung unter Windows von der Standardeinstellung unter Linux unterscheidet, so dass es sich lohnt, den Pufferungstyp trotzdem einzustellen, um ein einheitliches Verhalten zu erreichen.

2voto

Daniel Pratt Punkte 11859

Ich bin ein ziemlicher Haskell-Neuling, aber ich erinnere mich, dass ich kürzlich auf ein Beispiel für die Verarbeitung von Eingaben Zeichen für Zeichen gestoßen bin. Ist hSetBuffering vielleicht das, wonach Sie suchen?

0voto

Christian Brolin Punkte 101

Pufferung ist eine Sache, aber Sie verwenden auch gGetLine die auf eine ganze Zeile (oder das Ende der Datei) wartet. Erwägen Sie die Verwendung von hGetChar wenn Sie wirklich eine Figur nach der anderen lesen wollen. Eine andere Möglichkeit, die Pufferung zu überwinden, ist die Verwendung von hFlush .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X