1

I have a computer algebra program (called Reduce) that works in the shell in an interactive manner: launch Reduce in the shell, then you can define variables, compute this and that, and what not. Reduce prints the output into the shell. My idea is that I want to build a frontend for this text-based program that evaluates its output and converts it into a nice LaTeX style formula. For this I want to use Java.

I can start Reduce via exec(). But how can I emulate text input to the opened shell, and how can I read back what Reduce writes into the shell?

Thanks Jens

Edit 1: Current Code

// get the shell
Runtime rt = Runtime.getRuntime();

// execute reduce
String[] commands = {"D:/Programme/Reduce/reduce.com", "", ""};
Process proc = null;
try {
    proc = rt.exec(commands);
} catch (Exception e) {
    System.out.println("Error!\n");
}

// get the associated input / output / error streams
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedWriter stdOutput = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));

// read the output from the command
System.out.println("Here is the standard output of the command:\n");
String s = null;
try {
    while ((s = stdInput.readLine()) != null) {
        System.out.println(s);
    }
} catch (Exception e) {
}

// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
try {
    while ((s = stdError.readLine()) != null) {
        System.out.println(s);
    }
} catch (Exception e) {
}
Jens
  • 49
  • 2
  • 13

3 Answers3

1

You need to get the streams associated with the process including the InputStream, OutputStream, and ErrorStream. You then can send messages to the process via the OutputStream and then read info from the process via the InputStream and the ErrorStream.

From some code of mine:

  final ProcessBuilder pBuilder = new ProcessBuilder(TEST_PROCESS_ARRAY);

  final Process proc = pBuilder.start();

  procInputStream = proc.getInputStream();
  errorStream = proc.getErrorStream();

  errorSBuffer = new StringBuffer();
  streamGobblerSb = new StreamGobblerSb(errorStream, "Autoit Error", errorSBuffer);
  new Thread(streamGobblerSb).start();

  final Scanner scan = new Scanner(procInputStream);
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Thanks, but I could not find the class StreamGobblerSb in the Java documentation. Where can I find it? – Jens Jul 12 '14 at 16:02
  • @Jens: Oh, sorry, those are simply my Runnable classes to handle the streams. You will need to create your own Runnable to handle the Streams within background threads. – Hovercraft Full Of Eels Jul 12 '14 at 16:03
  • Ah OK, then it is just the StreamGobbler class mentioned here? http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html. I guess I realized that I need threads, my code from edit no.1 above hangs itselft after successful launch of the application. – Jens Jul 12 '14 at 16:06
  • @Jens: the article that you link to is one of the seminal articles on Java background process work, and I suggest that you study it well. Some of it is a little out of date, such as for instance most will use a ProcessBuilder and not Runtime to create the process, but its salient points are still crucial and correct. – Hovercraft Full Of Eels Jul 12 '14 at 16:55
0

You may want to look into using the Process class.

http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html

I believe you may be able to start the process, and then use getOutputStream() to feed commands into the process.

oapeter
  • 29
  • 4
  • Thanks! See my edit no. 1 above for the current status. The problem is that the while loop hangs itself while waiting for more output... Can I put this in a thread or something? – Jens Jul 12 '14 at 16:03
  • Yep, You can use a thread for each of the Streams. Here's an example that I've seen: http://stackoverflow.com/a/3350862 – oapeter Jul 12 '14 at 22:55
-1

While this is not strictly an answer, I discovered that it is more convenient for me to stick with PHP's function proc_open(). That way I can include the output directly in the frontend and do not need to worry about the communication between my Java program and the html frontend.

For everybody who wants to stick to the Java method: the article http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html is a good reference.

Jens
  • 49
  • 2
  • 13