我正在从Java程序中执行Native窗口中的cmd进程。我希望能够查看分叉进程的输入和输出。但是,我似乎无法从Java程序中编写任何内容。
当我尝试在Windows中的命令提示符上写一组字符时,我有点期待它在屏幕上打印一些东西 - 任何东西。所以,如果我给它荒谬的垃圾,那么它应该打印它不理解该命令。
但是,在将以下代码中的垃圾String写入子进程的OutputStream之后:
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("cmd");
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
PrintWriter out = new PrintWriter(process.getOutputStream());
String line = null;
out.println("My Garbage String");
while((line = readLine()) != null)
System.out.println(line);
程序在while((line = readLine()) != null)
处停止。
因此,父进程显然是阻塞的,直到子进程获得一些输入并解除阻塞并将该输入发送到父进程。但是,当我在PrintWriter
的{{1}}方法上写任何内容时,我正在给孩子处理一些输入,不是吗?
的更新 的
现在,由于给我的一些答案,我决定澄清我的问题是什么。我可以从命令提示符中读取输出。实际上,当我第一次运行它时,如果在命令提示符下键入“cmd”,我将获得与通常获得的相同的输出。
例如,请使用以下代码示例:
println()
代码的输出如下:
Microsoft Windows XP [版本5.1.2600](C)版权所有1985-2001 微软公司
如您所见,命令提示符为我的父进程提供了一些输出。但是,在我的IDE中以调试模式运行它时,我发现它只是停在Process process = Runtime.getRuntime().exec("cmd");
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
PrintWriter out = new PrintWriter(process.getOutputStream());
String line = null;
do
{
line = in.readLine();
System.out.println(line);
}while(line!=null)
行。因此,子进程阻塞,因为没有其他内容可以打印。
因此,当我尝试使用其line=in.readLine();
属性为其提供一些输入时,它似乎没有响应。相反,程序会阻塞OutputStream
。
回应一张海报建议的内容,你提到的文章(当Runtime.exec()不会)时,它只会从line=in.readLine();
和{{ 1}}属性。除了运行OutputStream
时以数组形式给出的初始执行参数之外,它没有提到我可以给它任何类型的输入。
为了模拟我最初想要做的事情(即,给它随机垃圾并打印它不理解命令),我可以只需输入ErrorStream
我的代码并运行它。但是,这不是我想要做的。我希望在它已经开始执行后与命令提示符进行通信。
最终,我希望能够与其他程序进行交互,这些程序通常需要您在从Java程序执行后与它们进行交互。然而,如果我能告诉它该做什么的唯一一次是当我指定其执行参数时,那么我将无法以我想要的方式使用Java与单独的进程交互。
如果有人知道如何实现这一目标,请告诉我。感谢。
答案 0 :(得分:3)
StreamGobbler
是谷歌为他们提供的方式。它们以新线程开始并正在读取输出。
一篇描述如何实现它们的好文章。 When Runtime.exec() won't
答案 1 :(得分:2)
这里有完整的样本。请注意,这会通过输出流运行dir命令。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
class StreamGobbler extends Thread {
InputStream is;
String type;
StreamGobbler(InputStream is, String type) {
this.is = is;
this.type = type;
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null)
System.out.println(type + ">" + line);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
public class GoodWindowsExec {
public static void main(String args[]) {
try {
String osName = System.getProperty("os.name");
String[] cmd = new String[1];
cmd[0] = "cmd.exe";
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(cmd);
proc.getOutputStream().write("dir \n".getBytes());
proc.getOutputStream().flush();
// any error message?
StreamGobbler errorGobbler = new StreamGobbler(
proc.getErrorStream(), "ERROR");
// any output?
StreamGobbler outputGobbler = new StreamGobbler(
proc.getInputStream(), "OUTPUT");
// kick them off
errorGobbler.start();
outputGobbler.start();
// any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
答案 2 :(得分:1)
Java程序控制process.getOutputStream()的输入。如果要将数据发送到程序,则需要从Java发送数据。
答案 3 :(得分:0)
你很困惑。 首先,当前的描述是混乱的,你应该重写它。
其次,按照 Farmor 的回答提供StreamGobbler。
您对
的期望是什么?out.println("My Garbage String");
while((line = readLine()) != null)
...
它完全符合它所说的。将字符串发送到外部进程的输入流,而不是在相同的输入流中等待任何字符串到达。你之前寄过的那个当然是早已不复存在。
答案 4 :(得分:0)
“程序停在它所说的位置((line = readLine())!= null)。”
答案可能是单独的问题Java Process with Input/Output Stream(来自Luke Woodward的回答):
..循环while((line = readLine())!= null) 只有在读取器退出时才会从进程的标准中读取 输出,返回文件结尾。 只有在流程退出时才会发生这种情况。 如果目前没有发生,它将不会返回文件结尾 来自流程的更多输出。相反,它将等待下一行 来自流程的输出,直到它有下一行才返回。
尝试使用一个线程将命令写入process.getOutputStream(),然后使用第二个线程读取process.getInputStream()。