我需要使用流程构建器运行shell脚本或系统命令。在某些情况下,该命令将要求用户输入。例如,我有一个java程序" TestScanner"从命令行获取一个整数并将其打印出来。如果我直接在终端中运行它,比如
$bash -c "java TestScanner"
Enter a number:3
Number entered:3
$
程序显示输入消息。然后我输入" 3"然后打印出结果并终止程序。
现在我需要运行命令
bash -c "java TestScanner"
来自java进程构建器的。代码是
// cmdList has 3 elements: bash, -c, java TestScanner
ProcessBuilder pb = new ProcessBuilder(cmdList);
pb.redirectErrorStream(true);
pb.directory(new File(workDir));
Process p = pb.start();
InputStream in = p.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = null;
while ((line = br.readLine()) != null)
{
System.out.println("Line: " + line);
}
当我运行上面的代码片段时,它只是挂在那里。我甚至看不到消息"输入一个数字"。我不确定这是否是因为p.getOutputStream()正在等待?如何检测程序请求输入?我在这里尝试了代码片段Java Process with Input/Output Stream,但在我的情况下它不起作用。感谢
答案 0 :(得分:1)
假设您有一个进程p,您可以让InputStream读取进程打印的内容,就像您所做的那样。但是如果你想要提供一些输入,你必须使用该过程的OutputStream。
Process p=pb.start();
OutputStream os = p.getOutputStream();
PrintWriter writer=new PrintWriter(os);
writer.write("1\n"); //'\n' to simulate enter key
在你的情况下,似乎“输入数字:”行没有换行符或'\ n'字符末尾,所以从技术上讲它不是一行。因此使用缓冲读取器读取线将没有帮助。对于长期挂在那里的程序来说,这可能是一个问题。
答案 1 :(得分:0)
您是否必须使用ProcessBuilder?使用java.io.Console类可以实现同样的目的。
答案 2 :(得分:0)
在研究了MadProgrammer的精彩教程(见他的评论)之后,我看到了我的问题中发生了什么。
InputStream in = p.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = null;
while ((line = br.readLine()) != null) {...}
此处BufferedReader正在尝试读取一行(由EOL终止),但是在用户向OutputStream输入内容并按Enter键之前,进程对象返回的InputStream从未到达EOL。这就是为什么提示信息"输入数字"没有出现。将读取方法更改为
is.read() != -1
while循环中的将显示提示消息。那么问题是如何检测用户输入。当用户输入内容并按Enter键时,数据位于OutputStream的缓冲区中。我们需要实现的是" sense"有些东西在OutputStream中,需要写入并刷新。在我的情况下,我有一个SWT文本供用户输入数据,所以我在Text控件中添加了一个SWT.DefaultSelection事件监听器来响应键盘输入。然后我看到了正确的程序输出。