Redirect stdin and stdout in Java

18,630

Solution 1

You've attempted to write to the output stream before you attempt to listen on the input stream, so it makes sense that you're seeing nothing. For this to succeed, you will need to use separate threads for your two streams.

i.e.,

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Scanner;

public class Foo {
   public static void main(String[] args) throws IOException {
      Process cmd = Runtime.getRuntime().exec("cmd.exe");

      final InputStream inStream = cmd.getInputStream();
      new Thread(new Runnable() {
         public void run() {
            InputStreamReader reader = new InputStreamReader(inStream);
            Scanner scan = new Scanner(reader);
            while (scan.hasNextLine()) {
               System.out.println(scan.nextLine());
            }
         }
      }).start();

      OutputStream outStream = cmd.getOutputStream();
      PrintWriter pWriter = new PrintWriter(outStream);
      pWriter.println("echo Hello World");
      pWriter.flush();
      pWriter.close();
   }
}

And you really shouldn't ignore the error stream either but instead should gobble it, since ignoring it will sometimes fry your process as it may run out of buffer space.

Solution 2

Nowadays Runtime.getRuntime().exec() is deprecated (for all practical purposes). Better use the ProcessBuilder class; in particular, its start() method will return a Process object with methods for accessing the stdin and stdout streams, which can be redirected wherever you need them. Take a look at this post for further details.

Share:
18,630
Josh
Author by

Josh

Updated on June 04, 2022

Comments

  • Josh
    Josh almost 2 years

    I'm trying to redirect stdin and stdout of a subprocess in java, eventually i'm going to have the output go to a JTextArea or something.

    Here is my current code,

    Process cmd = Runtime.getRuntime().exec("cmd.exe");
    
    cmd.getOutputStream().write("echo Hello World".getBytes());
    cmd.getOutputStream().flush();
    
    byte[] buffer = new byte[1024];
    cmd.getInputStream().read(buffer);
    String s = new String(buffer);
    
    System.out.println(s);
    

    The output looks like this:

    Microsoft Windows [Version 6.1.7601]
    Copyright (c) 2009 Microsoft Corporation.  All rights reserved.
    
    C:\(Current Directory)>
    

    I'm expecting to see the "Hello World" string outputted. Maybe because the parent process isn't staying alive long enough?

    I'd also like to be able to send and receive multiple commands.

  • Marcos Dione
    Marcos Dione over 7 years
    @Hovevercraft: you say that he's “you attempted to write to the output stream before you attempt to listen on the input stream, so it makes sense that you're seeing nothing”. I don't understand why reading after the command was written would lead to a short read. In fact, you say "seeing nothing", but at least he's seeing cmd.exe's banner and prompt. I have the impression that if he read again, he would see the rest of it. What I'm missing?