Sim
Sim

Reputation: 4184

How to send EOF using scala process utility

I want to start a python program from inside a scala program that has to receive a possibly infinitely long string. Thus it is not possible to pass it as a cmd argument.

My solution is to transmit the data via the stdstreams. However, I am unable to find the scala version of the working bash code:

bash code:

#/bin/bash
var="SOME REALLY LONG STRING THAT IS SEND TO THE PYTHON PROGRAM"
echo "$var" | ./readUntilEOF.py

scala code:

import sys.process._
 
object main {

       def main(args : Array[String]) : Unit = {
           val cmd = "./readUntilEOF.py"
           val string = "SOME REALLY LONG STRING THAT IS SEND TO THE PYTHON PROGRAM"
           print("I am starting to send stuff...")
           val resultString = (string #| cmd.!!).!!
           print(resultString)
       }
 
}

readUntilEOF.py:

#!/usr/bin/python3

import sys

if __name__ == "__main__":
    read = sys.stdin.read()
    print(read)

Output running the bash command:

#> ./scalaBashEquivalent.sh 
SOME REALLY LONG STRING THAT IS SEND TO THE PYTHON PROGRAM


Output running the scala code:

#> scala scala.sc
I am starting to send stuff...
/* and then it never terminates */

Upvotes: 0

Views: 121

Answers (2)

Mario Galic
Mario Galic

Reputation: 48410

#< can take InputStream so try

(cmd #< new ByteArrayInputStream(string.getBytes)).!!

scastie

Upvotes: 2

Sim
Sim

Reputation: 4184

It is indeed a bit more complex than expected. But the below code seems to work.

import java.io.PrintWriter

object main {

       def main(args : Array[String]) : Unit = {
           val cmd = "./readUntilEOF.py"
           val string = "SOME REALLY LONG STRING THAT IS SEND TO THE PYTHON PROGRAM"
           println("I am starting to send stuff...")
           val processOutput : StringBuilder = new StringBuilder()
           val process = Process(cmd).run(new ProcessIO(
               in => {
                  val writer = new PrintWriter(in)
                  writer.write(string)
                  writer.close()
               },
               out => {
                   processOutput.addAll(scala.io.Source.fromInputStream(out))
                   out.close()
               },
               _.close()
           ))
           assert(process.exitValue() == 0)
           print(processOutput.toString)
       }

}

Upvotes: 0

Related Questions