在Common Lisp中读取外部程序的二进制输出 [英] Reading the binary output of an external program in Common Lisp

查看:177
本文介绍了在Common Lisp中读取外部程序的二进制输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在SBCL中运行外部程序并捕获其输出。
输出为二进制数据(PNG图像),而SBCL坚持将其解释为字符串。

I'm trying to run an external program in SBCL and capture its output. The output is binary data (a png image), while SBCL insists on interpreting it as strings.

我尝试了多种方式,例如

I tried a number of ways, like

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

但是我遇到类似错误

Illegal :UTF-8 character starting at byte position 0.

在我看来,SBCL试图将二进制数据解释为文本并对其进行解码如何更改此行为?我只对获取八位字节的向量感兴趣。

It seems to me that SBCL is trying to interpret the binary data as a text and decode it. How do I change this behaviour ? I'm interested only in obtaining a vector of octets.

编辑:因为从上面的文本中不清楚,我想补充一下,至少在flexi-stream的情况下,流的元素类型是 flexi-streams:octect (这是(无符号字节8))。
我希望至少在这种情况下, run-program 会读取原始字节而没有很多问题。相反,我收到类似的消息,不知道如何复制到元素类型的流(UNSIGNED-BYTE 8)

Since it is not clear from the text above, I'd like to add that at least in the case of flexi-stream, the element-type of the stream is a flexi-streams:octect (which is a (unsigned-byte 8)). I would expect at least in this case run-program to read the raw bytes without many issues. Instead I get a message like Don't know how to copy to stream of element-type (UNSIGNED-BYTE 8)

推荐答案

编辑:我很生气,因为无法完成这个非常简单的任务并解决了问题。

I got angry at not being able to do this very simple task and solved the problem.

功能上,由于我不了解的原因,将UNSIGNED-BYTE类型的流发送到运行程序并使其正常工作的能力受到严重限制。我尝试了灰度流,flexi流,fd流以及其他一些机制,例如您。

Functionally, the ability to send a stream of type UNSIGNED-BYTE into run-program and have it work correctly is severely limited, for reasons I don't understand. I tried gray streams, flexi-streams, fd streams, and a few other mechanisms, like you.

但是,仔细阅读运行程序的源代码(第五或第六次) ),我注意到有一个选项:STREAM可以传递给输出。鉴于此,我想知道读字节是否可以工作……而且确实可以。为了提高性能,可以确定如何获取非文件流的长度并对其执行READ-SEQUENCE。

However, perusing run-program's source (for the fifth or sixth time), I noticed that there's an option :STREAM you can pass to output. Given that, I wondered if read-byte would work... and it did. For more performant work, one could determine how to get the length of a non-file stream and run READ-SEQUENCE on it.

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

这篇关于在Common Lisp中读取外部程序的二进制输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆