【问题标题】:Scala: Get Scala Stream+Process instance from ProcessBuilderScala:从 ProcessBuilder 获取 Scala Stream+Process 实例
【发布时间】:2016-05-10 21:12:55
【问题描述】:

我有以下选择:

选项 #1:lineStream(log: ProcessLogger): Stream[String](和 3 个类似选项)

选项 #2:run(log: ProcessLogger): Process(和 4 个类似选项)

我怎样才能同时获得Stream[String] + Process

如果不可能,当我决定使用第一个选项(Stream[String] 但没有Process 实例)时,如何提前销毁系统进程?

Related API Docs Page (ProcessBuilder)

【问题讨论】:

    标签: scala stream processbuilder


    【解决方案1】:

    这是我不喜欢 Scala 中的流程 API 的原因之一——您通常可以继续使用,或者两者兼而有之。我不认为你想要的 API 是可能的。如果你看ProcessBuilderImpl.lineStream()的实现,进程引用只存储在本地,没有访问权限。

    这里有一个简单的示例,您可以根据lineStream() 的实际编写方式(参见ProcessBuilderImplBasicIO)来自己实现这些功能。我没有时间完善它(比如返回比元组更好的东西),但它应该给你一个想法。

      object StreamProcessLogger {
        private val nonzeroException = true // set it to whatever suits you
    
        def run(processBuilder: ProcessBuilder): (Process, Stream[String]) = {
          val logger = new StreamProcessLogger
          val process = processBuilder.run(logger)
          waitForExitInAnotherThread(process, logger)
          (process, logger.stream)
        }
    
        private def waitForExitInAnotherThread(process: Process, logger: StreamProcessLogger) = {
          val thread = new Thread() {
            override def run() = { logger.setExitCode(process.exitValue()) }
          }
          thread.start()
        }
    
      }
    
      private class StreamProcessLogger extends ProcessLogger {
        val queue = new LinkedBlockingQueue[Either[Int, String]]
    
        override def buffer[T](f: => T): T = f
        override def out(s: => String): Unit = queue.put(Right(s))
        override def err(s: => String): Unit = queue.put(Right(s))
    
        def stream = next()
        def setExitCode(exitCode: Int) = queue.put(Left(exitCode))
    
        private def next(): Stream[String] = queue.take match {
          case Left(0) => Stream.empty
          case Left(code) => if (StreamProcessLogger.nonzeroException) scala.sys.error("Nonzero exit code: " + code) else Stream.empty
          case Right(s) => Stream.cons(s, next())
        }
      }
    

    这是用法:

    test("returns stream and process") {
      val (process, stream) = StreamProcessLogger.run(Process("ls"))
      stream.foreach(println)
      println(process.exitValue())
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-23
      相关资源
      最近更新 更多