Перенаправить стандартный ввод и стандартный вывод в Java

Я пытаюсь перенаправить стандартный ввод и стандартный вывод подпроцесса в java, в конце концов я собираюсь вывести вывод в JTextArea или что-то в этом роде.

Вот мой текущий код,

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);

Вывод выглядит следующим образом:

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\(Current Directory)>

Я ожидаю увидеть вывод строки «Hello World». Может быть, потому, что родительский процесс не живет достаточно долго?

Я также хотел бы иметь возможность отправлять и получать несколько команд.


person Josh    schedule 02.05.2012    source источник


Ответы (2)


Вы попытались записать в выходной поток до того, как попытаетесь прослушать входной поток, поэтому вполне логично, что вы ничего не видите. Чтобы это удалось, вам нужно будет использовать отдельные потоки для ваших двух потоков.

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();
   }
}

И вы действительно не должны игнорировать поток ошибок, а вместо этого должны сожрать его, так как его игнорирование иногда может поджарить ваш процесс, поскольку ему может не хватить места в буфере.

person Hovercraft Full Of Eels    schedule 02.05.2012
comment
@Hovevercraft: вы говорите, что он «пытался записать в выходной поток, прежде чем пытаться прослушать входной поток, поэтому имеет смысл, что вы ничего не видите». Я не понимаю, почему чтение после написания команды приводит к короткому чтению. На самом деле, вы говорите, что ничего не видите, но, по крайней мере, он видит баннер и подсказку cmd.exe. У меня такое впечатление, что если он прочитает еще раз, то увидит все остальное. Что мне не хватает? - person Marcos Dione; 29.08.2016

В настоящее время Runtime.getRuntime().exec() устарел (для всех практических целей). Лучше использовать класс ProcessBuilder; в частности, его метод start() вернет процесс с методами доступа к потокам stdin и stdout, которые можно перенаправить туда, куда вам нужно. Взгляните на этот сообщение для получения дополнительной информации.

person Óscar López    schedule 02.05.2012