Вывод сокращается с использованием scala.sys.process и ByteArrayOutputStream - PullRequest
0 голосов
/ 06 июня 2018

Я хочу запустить команду и получить вывод без промежуточных файлов.Обычно это работает, но иногда усекает вывод.

Например, если я запусту эту программу, она всегда будет генерировать один и тот же вывод и посчитает количество байтов на нем:

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)
}

Я все еще хотел бы знать, в чем проблема с исходным кодом.

...