2016-01-25 33 views
6

Występuję proces z programu Common Lisp (gnuplot). Potrafię ustanowić strumienie wejściowe i wyjściowe dla procesu. Mam jednak problem z odczytaniem wyniku. Problem polega na tym, że chcę próbować odczytać wynik, a jeśli nic tam nie ma, cóż ... na przykład nic nie rób.Jak wykryć, czy strumień wejściowy jest pusty (ale nie EOF)?

(problem podstawowy: Chcę odczytać wynik polecenia show term ale chcę pominąć żadnego innego wyjścia, że ​​gnuplot może przyniosły przed wysłaniem tej komendy)

Gdybym po prostu użyć (read-line gnuplot-output nil :eof) i nie ma nic strumień wyjściowy, nie będzie wskazywał :eof (ponieważ strumień jest wciąż żywy i coś tam może się tam pojawić) i po prostu zablokuje się, dopóki nie będzie czegoś do odczytu (tj. na zawsze).

Czy można wykryć, że nie ma nic do czytania? Przynajmniej w jakiś sposób bezpiecznie przerwać próbę odczytania (tj. Nie powinien wysuwać nowej linii ze strumienia po osiągnięciu limitu czasu)?

PS. Używam SBCL

Odpowiedz

5

Listen powinieneś powiedzieć, czy jest dostępna postać. Myślę, że będziesz musiał czytać strumień po znaku, a nie całe linie, chyba że masz pewność, że program nigdy nie wyprowadza niekompletnej linii.

Edit: Szybki test (za pomocą SB-ext do uruchomienia programu):

(defun test() 
    (do* ((program (run-program "output-test.sh" nil 
           :search t 
           :output :stream 
           :wait nil)) 
     (output-stream (process-output program))) 
     ((not (process-alive-p program))) 
    (if (listen output-stream) 
     (loop 
      for char = (read-char-no-hang output-stream nil nil) 
      while char 
      do (write-char char)) 
     (format t "No output available.~%")) 
    (sleep 1))) 

Gdzie output-test.sh jest:

#!/bin/sh 
for item in * 
do 
    echo $item 
    sleep 3 
done 
+1

1+ OP: patrz również 'read-char-no-hang' – coredump

+0

Używając' read-char-no-hang', nie musisz używać 'listen'. Ponadto, zwijanie zmiennych wiązań z zewnętrznego 'let' /' let * 'do wewnętrznego 'do' /' do * ', tak jak w przypadku jednej z twoich edycji, utrudnia czytelność kodu i łatwość konserwacji, aby zapisać tylko kilka znaków. Zarówno 'program' i' output-stream' nie różnią się w pętli, więc pozostawienie ich w zewnętrznym 'let' /' let * 'uczyniłoby to oczywistym. – acelent

+0

@acalent 'listen' to sprawdzenie, czy jest cokolwiek do czytania, bez czytania go. Używanie tylko 'read-char-no-hang' pochłonie pierwszy znak wejścia, czyniąc logikę bardziej skomplikowaną. Jeśli chodzi o posiadanie zmiennych powiązań w oddzielnym 'let', pomyślałem, że na początku byłoby to bardziej zrozumiałe, ale potem zorientowałem się, że skoro pętla ma działać do momentu wyjścia programu, to ma sens aby program został uruchomiony w pętlach inicjalizacja. W ten sposób całe życie procesu potomnego jest w jednym miejscu. – jkiiski