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
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.
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.
close() method closes the input stream reader and invocations to read(), ready(), mark(), reset(), or skip() method on a closed stream will throw IOException.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With