2016-06-28 2 views
1

В принципе, у меня есть программа, выход которой идет на стандартный вывод. Я запускаю эту программу из моего кода Scala. Сейчас я хочу перенаправить вывод в файл. Что-то вроде этого.Как пропустить stdout в Scala?

val cmd = progName + " " + arguments 
cmd #> new java.io.File(outputFilePath) ! 

Мне также необходимо обработать этот выходной файл. Вот почему этот подход медленный, так как я должен сначала дождаться завершения программы, и все будет записано в выходной файл. Я бы предпочел, чтобы содержимое потока stdout транслировалось так, что из другого потока я мог читать содержимое по мере его потоковой передачи. Таким образом, я могу обрабатывать данные во время работы программы, которую я запускаю из Scala.

Кроме того, данные в выходном файле разделены символами новой строки. Есть ли способ, я могу получить данные по очереди, когда программа запущена.

И, наконец, есть ли что-то в Java, чтобы это сделать, и затем я могу использовать его в Scala?

+0

Посмотрите на Scala [ProcessBuilder] (http://www.scala-lang.org/api/current/index.html#scala.sys.process.ProcessBuilder), чтобы увидеть, как перенаправить стандартный вывод – cchantep

+0

Я не знаю достаточно о Scala, но это может быть дубликат [this] (http://stackoverflow.com/a/5564667/1863564). –

ответ

4

У ProcessBuilder есть метод lineStream, который, я думаю, делает именно то, что вы хотите. Он возвращает Stream[String], который позволяет обрабатывать вывод по мере его появления.

Вот простая программа, с медленным выходом для тестирования, которое я сохранил в slow-printer.scala:

// slow-printer.scala 
for (i <- 1 to 10) { 
    println(i) 
    Thread.sleep(1000) 
} 

Вы можете передавать выходной (1 строка в секунду) из программы, как это:

import scala.sys.process._ 

val lines = "scala slow-printer.scala".lineStream 

lines foreach println 

Если вы застряли с 2.10, или, может быть, если ваш вывод не связан с новой линией, вы можете использовать ProcessIO для обработки вывода:

import scala.sys.process._ 

Seq("scala", "slow-printer.scala").run(new ProcessIO(
    _.close(), // stdin 
    out => { // stdout 
    val src = scala.io.Source.fromInputStream(out) 
    for (line <- src.getLines()) { 
     println(line) 
    } 
    }, 
    _.close() // stderr 
)) 
+0

Выполняют ли здесь параллельные строки «val lines = ....» и «lines foreach println»? – pythonic

+0

Да, подпроцесс выполняется параллельно с строками, которые печатаются в основной программе Scala. Попробуй! Вы увидите одну строку, напечатанную в секунду. – DaoWen

+0

Какая версия Scala требует этого? Потому что я получаю следующую ошибку: : 38: error: value lineStream не является членом String val lines = "./my-cmd.sh".lineStream ^ : 34: error: значение foreach is не входит в Int строки foreach println – pythonic

Смежные вопросы