Re: Reading Binary Data from Pipe Streams
"Yuri Davidovsky" <yury.davidouski2@mail.dcu.ie> writes:
> Hi guys,
>
> it appears to me that it is not possible to read binary data from
> pipes in LIspworks on Windows, but maybe I am wrong. The way I am
> trying to do it at the moment is this:
>
> (defun test (command)
> (with-open-stream (s (sys:open-pipe command
> :direction :input :element-type '(signed-byte 32)))
> (let ((out (make-array 44100 :element-type '(signed-byte 32))))
> (loop for pos from 0
> for byte = (read-byte s nil #\Null)
> while byte do (setf (aref out pos) byte))
> out)))
>
> What is happening there is very simple: I am trying to request one
> second of audio data from a console application in 32 signed format
> and write it to an array for further manipulation. Of course it is
> possible to do it by requesting the utility to write an intermediate
> file but I think that a pipe approach is a bit cleaner.
>
> What is happening at the moment, I get an error "Error:
> STREAM:STREAM-READ-BYTE is not implemented for this stream type:
> #<WIN32::PROCESS-PIPE-STREAM 21F424E3>" Now, I am using a random
> termination character #\Null for read-byte because I do not know
> better at the moment.
>
> read-sequence does not seem to work either.
>
> Any input would be greatly appreciated,
Using anything but (unsigned-byte 8) may require a file format including
a descriptive header. It would be difficult to establish a file header
on a pipe.
So you should rather use (unsigned-byte 8) as element-type and decompose
and combine bytes for transmission. (cf. ldb and dpb, with byte).
Notice by the way that you've not specified an :external-format to
open-pipe, therefore you didn't specify any bytesex for your 32-bit
values. Do you know what byte-sex would be used when reading (from
files) (signed-byet 32)? I'm not saying that it's possible to give an
:external-format specifying the byte-sex (check the documentation).
But this is something that you should explicitely manage one way or
another. Reading (unsigned-byte 8) bytes, you will explicitely
recompose big-endian or little-endian words to make your (signed-byte
32) values.
Now, the object to be returned by read-byte (or read) upon end-of-file
can by of any type, so you can indeed give a character such as #\Null
(and get it back into byte) when end-of-file occurs, but #\Null is true,
so it won't stop the loop, and it will break while trying to store this
character into the output vector of (signed-byte 32). You seem to be
wanting to get nil instead, so pass that instead of #\Null to read-byte.
--
__Pascal Bourguignon__
http://www.informatimago.com/
_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html