Mar*_*ele 5 sbcl common-lisp stream
我正在尝试在SBCL中运行外部程序并捕获其输出.输出是二进制数据(png图像),而SBCL坚持将其解释为字符串.
我试过很多方法,比如
(trivial-shell:shell-command "/path/to/png-generator" :input "some input")
(with-input-from-string (input "some input")
(with-output-to-string (output)
(run-program "/path/to/png-generator" () :input input :output output))
(with-input-from-string (input "some input")
(flexi-streams:with-output-to-sequence (output)
(run-program "/path/to/png-generator" () :input input :output output))
Run Code Online (Sandbox Code Playgroud)
但我得到的错误就像
Illegal :UTF-8 character starting at byte position 0.
Run Code Online (Sandbox Code Playgroud)
在我看来,SBCL正试图将二进制数据解释为文本并对其进行解码.我该如何改变这种行为?我只对获取八位字节的向量感兴趣.
编辑:由于上面的文字不清楚,我想补充一点,至少在flexi-stream的情况下,流的元素类型是a flexi-streams:octect
(这是a (unsigned-byte 8)
).我希望至少在这种情况下run-program
读取原始字节没有很多问题.相反,我收到了一条消息Don't know how to copy to stream of element-type (UNSIGNED-BYTE 8)
编辑:我对无法完成这个非常简单的任务感到生气并解决了这个问题。
从功能上讲,由于我不明白的原因,将 UNSIGNED-BYTE 类型的流发送到运行程序并使其正常工作的能力受到严重限制。我尝试了灰色流、灵活流、fd 流和其他一些机制,就像你一样。
但是,仔细阅读 run-program 的源代码(第五次或第六次),我注意到有一个选项 :STREAM 您可以传递给输出。鉴于此,我想知道 read-byte 是否会起作用……它确实起作用了。对于更高性能的工作,可以确定如何获取非文件流的长度并对其运行 READ-SEQUENCE。
(let*
;; Get random bytes
((proc-var (sb-ext:run-program "head" '("-c" "10" "/dev/urandom")
:search t
;; let SBCL figure out the storage type. This is what solved the problem.
:output :stream))
;; Obtain the streams from the process object.
(output (process-output proc-var))
(err (process-error proc-var)))
(values
;;return both stdout and stderr, just for polish.
;; do a byte read and turn it into a vector.
(concatenate 'vector
;; A byte with value 0 is *not* value nil. Yay for Lisp!
(loop for byte = (read-byte output nil)
while byte
collect byte))
;; repeat for stderr
(concatenate 'vector
(loop for byte = (read-byte err nil)
while byte
collect byte))))
Run Code Online (Sandbox Code Playgroud)