我想要做的是,使用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();
答案 0 :(得分:1)
首先,您需要同时使用stdout / stderr(通过单独的线程)。否则,您可以阻止生成的进程,因为您没有消耗其输出。有关详细信息,请参阅this answer。
要写入流程,我会将stdin
OutputStream
用BufferedWriter
打包,然后从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);
请注意以下事项:如果输入数据超过进程可以缓冲的数量,并且进程已经填充其输出缓冲区,并且您没有从输出缓冲区中读取,则会出现典型的死锁情况。在这种情况下,您必须在单独的进程中读取进程的输出并自行缓冲,或者首先将进程重定向到临时文件,然后在第二步中读取此内容。第一个变体性能更高,但第二个变量更容易理解,如果有大量数据并且性能不计算,也可能是一个有效的选项。