Common lisp 如何正确读取大型进程输出
关于如何从流程流中读取数据,已经有了很多讨论,但据我所知,这些讨论不包括从以下流程中读取数据:Common lisp 如何正确读取大型进程输出,common-lisp,sbcl,Common Lisp,Sbcl,关于如何从流程流中读取数据,已经有了很多讨论,但据我所知,这些讨论不包括从以下流程中读取数据: 在进行任何输出之前,可能会运行很长时间 在其生命周期结束时产生巨大的输出(超过流缓冲区所能容纳的容量) 不应超过给定的时间范围 结果输出作为一个整体需要(长字符串) 因此,使用上述解决方案会导致浪费进程周期,因为即使没有输出,循环也会尝试读取流,或者解决方案不会终止,因为进程无法打印其整个输出(由于缓冲区已满),并且输出处理程序在读取前等待进程终止 我当前的解决方案是这样的(灵感来源于大容量读取大
- 在进行任何输出之前,可能会运行很长时间
- 在其生命周期结束时产生巨大的输出(超过流缓冲区所能容纳的容量)
- 不应超过给定的时间范围
- 结果输出作为一个整体需要(长字符串)
(sb-ext:run-program "/path/to/programm"
(list "--params" "foo" "bar")
:output :stream :wait nil)
但这种解决方案有其缺点:
- 它不工作,因为流未与文件关联(错误)
- 它的一般睡眠时间为1,即使当时可能没有输出
- 它进行了大量的连接,这似乎是一个不雅观的解决方案
- 可能会运行很长时间(并在其生命周期结束时进行输出)
- 可能使输出大于流缓冲区
- 运行时间不得超过给定的时间跨度
- 整体上需要输出
?字符串输出流是否适合您?输出将存储在您随后返回的字符串中,因此缓冲不应该是一个太大的问题。例如:
* (with-output-to-string (out)
(sb-ext:run-program "/bin/ls" '("/") :output out))
"bin
boot
…
vmlinuz
vmlinuz.old
"
如果要预分配字符串,可以使用的string form参数对进行预分配
不过,您不必使用with output to string来使用字符串输出流。您还可以使用创建一个并将其传递给sb ext:run程序。你最终会从中获得文本。是否首先将输出重定向到一个文件,然后再读取该文件是一个选项?由于此函数将被多次调用,我宁愿不要,因为这将导致硬盘上大量不必要的写入和读取。虽然如果在RAM中有一个文件可能是一个不错的选择如果你担心流缓冲区的大小,你可以使用一个字符串输出流(如果你知道它有多大的话,可能是一个预分配的字符串)。那么你就不必担心缓冲区的大小了。不是重复的,而是相关的,因为问题演示了在这里的答案中使用的技术。更接近于复制品,但仍不完全相同。
* (with-output-to-string (out)
(sb-ext:run-program "/bin/ls" '("/") :output out))
"bin
boot
…
vmlinuz
vmlinuz.old
"