У меня есть Iterable [String], и я хочу передать это внешнему процессу и вернуть Iterable [String] для вывода.Поток ввода для внешнего процесса в Scala
Я чувствую, как это должно работать, как он компилирует
import scala.sys.process._
object PipeUtils {
implicit class IteratorStream(s: TraversableOnce[String]) {
def pipe(cmd: String) = s.toStream.#>(cmd).lines
def run(cmd: String) = s.toStream.#>(cmd).!
}
}
Однако Scala пытается выполнить содержимое с вместо передать их в стандарт. Может кто-нибудь пожалуйста, скажите мне, что я делаю неправильно ?
UPDATE:
Я думаю, что моя первоначальная проблема заключалась в том, что s.toStream был быть неявно преобразован в ProcessBuilder, а затем выполняется. Это неверно, так как это вход для процесса.
У меня появилось следующее решение. Это кажется очень взломанным и неправильным, но, похоже, сейчас работает. Я не пишу это как ответ, потому что я чувствую, что ответ должен быть одной строкой, а не такой гигантской.
object PipeUtils {
/**
* This class feels wrong. I think that for the pipe command it actually loads all of the output
* into memory. This could blow up the machine if used wrong, however, I cannot figure out how to get it to
* work properly. Hopefully http://stackoverflow.com/questions/28095469/stream-input-to-external-process-in-scala
* will get some good responses.
* @param s
*/
implicit class IteratorStream(s: TraversableOnce[String]) {
val in = (in: OutputStream) => {
s.foreach(x => in.write((x + "\n").getBytes))
in.close
}
def pipe(cmd: String) = {
val output = ListBuffer[String]()
val io = new ProcessIO(in,
out => {Source.fromInputStream(out).getLines.foreach(output += _)},
err => {Source.fromInputStream(err).getLines.foreach(println)})
cmd.run(io).exitValue
output.toIterable
}
def run(cmd: String) = {
cmd.run(BasicIO.standard(in)).exitValue
}
}
}
EDIT
Мотивация это происходит от использования функции .pipe искры на РДУ. Я хочу, чтобы эта точно такая же функциональность в моем локальном коде.
Вы правы неявного преобразования из 's.toStream' к ProcessBuilder. В любом случае, не будет 'def pipe (cmd: String): Stream [String] = (cmd +: s.toSeq) .lineStream' тоже работает или я что-то упускаю? – edi
Как это работает для бесконечного потока в качестве входных данных? Или в случае реального мира очень большой поток, который слишком велик, чтобы вписаться в Seq? – Jon
Хорошо, мне было непонятно, что ваш вход потенциально может быть очень большим. – edi