带有.exe的Java输入/输出流

时间:2011-03-08 19:39:01

标签: java input exe

我想要做的是,使用Java启动.exe控制台程序,并使用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 个答案:

答案 0 :(得分:1)

首先,您需要同时使用stdout / stderr(通过单独的线程)。否则,您可以阻止生成的进程,因为您没有消耗其输出。有关详细信息,请参阅this answer

要写入流程,我会将stdin OutputStreamBufferedWriter打包,然后从System.in

写入

答案 1 :(得分:1)

您可以创建另一个不断从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();

答案 2 :(得分:0)

使用ProcessBuilder API。它具有加入stderr和stdout流的非常方便的选项,因此您不必使用多个线程来从流中读取。

redirectErrorStream(true) 

是你的朋友。

如果您想将数据传递给流程:

proc.getOutputStream().write(allmydata);

阅读数据:

proc.getInputStream().read(byteBuffer);

请注意以下事项:如果输入数据超过进程可以缓冲的数量,并且进程已经填充其输出缓冲区,并且您没有从输出缓冲区中读取,则会出现典型的死锁情况。在这种情况下,您必须在单独的进程中读取进程的输出并自行缓冲,或者首先将进程重定向到临时文件,然后在第二步中读取此内容。第一个变体性能更高,但第二个变量更容易理解,如果有大量数据并且性能不计算,也可能是一个有效的选项。