如何使用scalaz流写入和读取外部进程

时间:2015-05-31 06:54:17

标签: scala scalaz scalaz-stream

我希望能够将scalaz流中的数据发送到外部程序,然后在将来的大约100ms内恢复该项目的结果。虽然我能够通过使用输入流Sink压缩输出流Process然后丢弃Sink副作用来使用下面的代码执行此操作,但我觉得此解决方案可能是非常脆弱。

如果外部程序的某个输入项有错误,则一切都将不同步。我觉得最好的办法是将一些增量ID发送到外部程序中,它可以在将来回显,以便在发生错误时我们可以重新同步。

我遇到的主要问题是将数据与程序Process[Task, Unit]的输出一起发送到外部程序Process[Task, String]的结果。我觉得我应该使用wyn中的某些东西,但不是很确定。

import java.io.PrintStream
import scalaz._
import scalaz.concurrent.Task
import scalaz.stream.Process._
import scalaz.stream._

object Main extends App {
/*
  # echo.sh just prints to stdout what it gets on stdin
  while read line; do
    sleep 0.1
    echo $line
  done
*/
  val p: java.lang.Process = Runtime.getRuntime.exec("/path/to/echo.sh")

  val source: Process[Task, String] = Process.repeatEval(Task{
     Thread.sleep(1000)
     System.currentTimeMillis().toString
  })

  val linesR: stream.Process[Task, String] = stream.io.linesR(p.getInputStream)
  val printLines: Sink[Task, String] = stream.io.printLines(new PrintStream(p.getOutputStream))

  val in: Process[Task, Unit] = source to printLines

  val zip: Process[Task, (Unit, String)] = in.zip(linesR)
  val out: Process[Task, String] = zip.map(_._2) observe stream.io.stdOutLines
  out.run.run
}

1 个答案:

答案 0 :(得分:0)

深入研究更高级的类型。看起来Exchange完全符合我的要求。

import java.io.PrintStream

import scalaz._
import scalaz.concurrent.Task
import scalaz.stream._
import scalaz.stream.io._

object Main extends App {
/*
  # echo.sh just prints to stdout what it gets on stdin
  while read line; do
    sleep 0.1
    echo $line
  done
*/
  val program: java.lang.Process = Runtime.getRuntime.exec("./echo.sh")

  val source: Process[Task, String] = Process.repeatEval(Task{
     Thread.sleep(100)
     System.currentTimeMillis().toString
  })

  val read: stream.Process[Task, String] = linesR(program.getInputStream)
  val write: Sink[Task, String] = printLines(new PrintStream(program.getOutputStream))
  val exchange: Exchange[String, String] = Exchange(read, write)
  println(exchange.run(source).take(10).runLog.run)
}