Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect if input stream is empty (but not EOF)?

I am spawning a process from Common Lisp program (gnuplot). I am able to establish input and output streams for the process. However, I have a problem reading from the output. The problem is that I want to try to read from the output, and if there is nothing there, well... do nothing for example.

(Basic problem: I want to read the result of the command show term but I want to skip any other output that gnuplot might have produced before sending this command)

If I just use (read-line gnuplot-output nil :eof) and there is nothing in output stream, it will not indicate :eof (since the stream is still alive and something might appear there) and will just block until it has something to read (i.e. forever).

Is there are way to detect that there is nothing to read? At least, somehow safely time-out the attempt to read (i.e. it shouldn't pop a new line out of the stream once the time-out is reached)?

PS. I am using SBCL

like image 609
mobiuseng Avatar asked Jan 25 '16 10:01

mobiuseng


People also ask

How do I know if InputStream is open?

There's no API for determining whether a stream has been closed. Applications should be (and generally are) designed so it isn't necessary to track the state of a stream explicitly. Streams should be opened and reliably closed in an ARM block, and inside the block, it should be safe to assume that the stream is open.

What is input stream in java?

InputStream class is the superclass of all the io classes i.e. representing an input stream of bytes. It represents input stream of bytes. Applications that are defining subclass of InputStream must provide method, returning the next byte of input.

How do I close InputStream?

close() method closes the input stream reader and invocations to read(), ready(), mark(), reset(), or skip() method on a closed stream will throw IOException.


1 Answers

Listen should tell you if there is a character available. I think you'll have to read the stream character by character rather than whole lines at a time, unless you're sure that the program never outputs an incomplete line.

Edit: A quick test (using sb-ext for running the program):

(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)))

Where output-test.sh is:

#!/bin/sh
for item in *
do
    echo $item
    sleep 3
done
like image 172
jkiiski Avatar answered Sep 27 '22 16:09

jkiiski