Потоки ввода / вывода Java с .exe - PullRequest
1 голос
/ 08 марта 2011

Я хочу запустить консольную программу .exe с Java и использовать Java для управления потоками ввода и вывода из окна консоли.Я знаю, что могу получать входной и выходной потоки из приложения, и вот как я это делаю в настоящее время:

    try {
        process = Runtime.getRuntime().exec("C:\\Users\\Owner\\Documents\\testApp\\console.exe");
    } catch (IOException e1) {
        e1.printStackTrace();
        return;
    }

    stdin = process.getOutputStream();
    stdout = process.getInputStream();

Затем я могу использовать BufferedReader, чтобы показать выходные данные, которые обычно отображает .exeОднако я не могу понять, как передать ввод из консольной программы приложения Java в реальный поток ввода .exe.Мне нужна помощь, как это сделать.

Редактировать: Хорошо, теперь у меня есть это, которое работает одновременно;однако, я не могу получить какой-либо вывод, связанный с любым вводом, который я беру из окна консоли Java.

    new Thread(new Runnable() {
        public void run() {
            String line;
            BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
            try {
                while ((line = br.readLine()) != null) {
                    System.out.println("[OUT] " + line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }).start();

    new Thread(new Runnable() {
        public void run() {
            try {
                byte[] buffer = new byte[1024];

                int bytesRead;
                while ((bytesRead = System.in.read(buffer)) != -1) {
                    for(int i = 0; i < buffer.length; i++) {
                        int intValue = new Byte(buffer[i]).intValue();
                        if (intValue == 0) {
                            bytesRead = i;
                            break;
                        }
                    }
                    // for some reason there are 2 extra bytes on the end
                    stdin.write(buffer, 0, bytesRead-2);
                    System.out.println("[IN] " + new String(buffer, 0, bytesRead-2) + " [/IN]");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }).start();

Ответы [ 3 ]

1 голос
/ 08 марта 2011

Вы можете создать другой поток, который постоянно читает из консоли Java, перезаписывая его на стандартный ввод процесса:

new Thread(
    new Runnable() {
      public void run() {
        try {
          byte[] buffer = new byte[1024];

          int bytesRead;
          while ((bytesRead = System.in.read(buffer)) != -1) {
            process.getOutputStream().write(buffer, 0, bytesRead);
          }
        } catch (IOException e) {
          // Do something with the error...
        }
      }
    }
  ).start();
1 голос
/ 08 марта 2011

Во-первых, вам нужно использовать stdout / stderr одновременно (через отдельные потоки).В противном случае вы можете заблокировать ваш порожденный процесс, так как вы не используете его вывод.См. этот ответ для получения более подробной информации.

Чтобы записать в процесс, я бы обернул stdin OutputStream BufferedWriter и просто записал бы в него из System.in

0 голосов
/ 08 марта 2011

Используйте API ProcessBuilder . Он имеет очень удобную опцию для объединения потоков stderr и stdout, поэтому вам не нужно использовать несколько потоков для чтения из потоков.

redirectErrorStream(true) 

твой друг здесь.

Если вы хотите передать данные процессу:

proc.getOutputStream().write(allmydata);

Чтобы прочитать данные:

proc.getInputStream().read(byteBuffer);

Обратите внимание на следующее: если входные данные больше, чем процесс может буферизовать, и если процесс уже заполнил свой выходной буфер, а вы не читаете из выходного буфера, у вас будет классическая ситуация взаимоблокировки. В этом случае вы либо должны прочитать выходные данные процесса в отдельном процессе и буферизировать его самостоятельно, либо вы сначала выполняете процесс, перенаправляющий данные во временный файл, и читаете это на втором шаге. Первый вариант более производительный, но второй более прост для понимания и может также быть допустимым, если данных много, а производительность не учитывается.

...