使用scala.sys.process和ByteArrayOutputStream

时间:2018-06-06 19:06:22

标签: scala concurrency io

我想运行命令并获取没有中间文件的输出。它通常有效,但有时会截断输出。

例如,如果我运行这个程序,它将始终生成相同的输出并计算其上的字节数:

object BugTest extends App {

  import java.io.ByteArrayOutputStream

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

  def run(): Array[Byte] = {
    val os = new ByteArrayOutputStream()
    val stderr = new StringBuilder
    val processLogger = ProcessLogger(x => stderr.append(x + "\n"), x => stderr.append(x + "\n"))
    val code = Seq("seq", "10000") #> os ! processLogger
    if (code != 0)
      throw new Exception(s"Got code $code: ${stderr.mkString}")
    os.close()
    os.toByteArray
  }

  val reference = run().size
  println(reference)
  var current = 0
  do {
    current = run().size
    println(current)
  } while (current == reference)
}

输出小于正确的输出会随机失败。执行示例:

48894
48894
48894
48894
48894
48894
48894
48894
48894
48128 <-- Truncated output !?

我做错了什么?

注意:在Scala 2.12.6上测试

更新

这段代码似乎没有任何问题(即它不断循环打印48894):

object BugTest extends App {

  import java.io._

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

  def outputProcessIO(stdout: OutputStream, stderr: OutputStream): ProcessIO = {
    new ProcessIO(
      _.close(),
     (is: InputStream) => BasicIO.transferFully(is, stdout),
     (is: InputStream) => BasicIO.transferFully(is, stderr)
    )
  }
  def run(): Array[Byte] = {
    val stdout = new ByteArrayOutputStream()
    val stderr = new ByteArrayOutputStream()
    val p = Seq("seq", "10000") run outputProcessIO(stdout, stderr)
    if (p.exitValue() != 0)
      throw new Exception(s"Got code $p: ${new String(stderr.toByteArray)}")
    stdout.toByteArray
  }

  val reference = run().size
  println(reference)
  var current = 0
  do {
    current = run().size
    println(current)
  } while (current == reference)
}

我仍然想知道原始代码的问题是什么。

0 个答案:

没有答案