gpt4 book ai didi

scala - 如何发出产生无限输出并立即返回的命令

转载 作者:行者123 更新时间:2023-12-02 20:41:19 25 4
gpt4 key购买 nike

当我编写以下代码时(在菊石中,但我认为这并不重要)

("tail -f toTail.txt"lineStream) foreach(println(_)),程序按照预期给了我最后一行,但随后挂起,即使我在文件,什么也没有出来。

API如何支持无限输出的过程?

我尝试编写val myStream = ("tail -f toTail.txt"lineStream_!)但它仍然没有返回写掉

这是 scala 文档的内容:

lineStream: returns immediately like run, and the output being generated is provided through a Stream[String]. Getting the next element of that Stream may block until it becomes available.

因此我不明白为什么它会阻止

顺便说一句,我与 Ammonite API 的行为完全相同

如果再次输入%%("tail", "-f", "toTail.txt"),该方法只会挂起并且不会立即返回。

最佳答案

ProcessBuilder 没有问题(至少不是源于您的用例的问题)。来自 ProcessBuilder documentation :

Starting Processes

To execute all external commands associated with a ProcessBuilder, one may use one of four groups of methods. Each of these methods have various overloads and variations to enable further control over the I/O. These methods are:

  • run: the most general method, it returns a scala.sys.process.Process immediately, and the external command executes concurrently.
  • !: blocks until all external commands exit, and returns the exit code of the last one in the chain of execution.
  • !!: blocks until all external commands exit, and returns a String with the output generated.
  • lineStream: returns immediately like run, and the output being generated is provided through a Stream[String]. Getting the next element of that Stream may block until it becomes available. This method will throw an exception if the return code is different than zero -- if this is not desired, use the lineStream_! method.

文档明确指出 lineStream 可能会阻塞,直到下一行可用。由于 tail -f 的本质是无限的行流 lineBreak,因此程序将阻塞等待下一行出现。

对于以下内容,假设我有一个文件:/Users/user/tmp/sample.txt,其内容为:

boom
bar
cat

为什么lineStream_!没有错

import scala.language.postfixOps
import scala.sys.process._

object ProcessBuilder extends App {

val myStream: Stream[String] = ("tail /Users/user/tmp/sample.txt" lineStream_!)
println("I'm after tail!")
myStream.filter(_ != null).foreach(println)
println("Finished")
System.exit(0)

}

输出:

I'm after tail!
boom
bar
cat
Finished

所以您会看到 lineStream_! 立即返回。因为命令的性质是有限的。

如何立即从产生无限输出的命令返回:

让我们用 tail -f 试试这个。您需要对流程进行更多控制。同样,正如文档所述:

If one desires full control over input and output, then a scala.sys.process.ProcessIO can be used with run.

举个例子:

import java.io.{BufferedReader, InputStreamReader}

import scala.language.postfixOps
import scala.sys.process._

object ProcessBuilder extends App {

var reader: BufferedReader = _
try {

var myStream: Stream[String] = Stream.empty
val processIO = new ProcessIO(
(os: java.io.OutputStream) => ??? /* Send things to the process here */,
(in: java.io.InputStream) => {

reader = new BufferedReader(new InputStreamReader(in))
myStream = Stream.continually(reader.readLine()).takeWhile(_ != "ff")
},
(in: java.io.InputStream) => ???,
true
)
"tail -f /Users/user/tmp/sample.txt".run(processIO)
println("I'm after the tail command...")

Thread.sleep(2000)
println("Such computation performed while tail was active!")

Thread.sleep(2000)
println("Such computation performed while tail was active again!")

println(
s"Captured these lines while computing: ${myStream.print(System.lineSeparator())}")

Thread.sleep(2000)
println("Another computation!")

} finally {
Option(reader).foreach(_.close())
}
println("Finished")
System.exit(0)

}

输出:

I'm after the tail command...
Such computation performed while tail was active!
Such computation performed while tail was active again!
boom
bar
cat

它仍然立即返回,现在它只是卡在那里等待更多输入。如果我从 tmp 目录执行 echo 'fff' >> sample.txt ,程序会输出:

Another computation!
Finished

您现在有权在发出 tail -f 命令后执行您想要的任何计算,并有权根据您传递给 takeWhile 的条件终止计算方法(或其他关闭输入流的方法)。

有关 ProcessIO 的更多详细信息,请查看 documentation here .

关于scala - 如何发出产生无限输出并立即返回的命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46026785/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com