2016-03-04 69 views
0

我需要使用进程生成器运行shell脚本或系统命令。在某些情况下,该命令将要求用户输入。例如,我有一个Java程序“TestScanner”,它从命令行获取一个整数并将其打印出来。如果我直接在终端运行它,像java进程生成器:使用用户输入从命令行运行程序

$bash -c "java TestScanner" 
Enter a number:3 
Number entered:3 
$ 

该程序显示消息输入。然后我输入“3”,然后打印结果并终止程序。

现在我需要从Java进程生成器运行的命令

bash -c "java TestScanner" 

。代码是

// 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代码片段,它不适用于我的情况。谢谢

+1

类似于[this](http://stackoverflow.com/questions/18838904/java-program-that-runs-commands-with-linux-terminal/18839348#18839348)或[this](http:// stackoverflow.com/questions/32343355/java-linux-terminal-in-jpanel/32343778#32343778) – MadProgrammer

+0

这非常有帮助。谢谢 – CMZS

回答

0

您是否必须使用ProcessBuilder?使用java.io.Console类可以达到相同的效果。

0

在研究了MadProgrammer的漂亮教程(请参阅他的评论)后,我看到了我的问题发生了什么。

InputStream in = p.getInputStream(); 
BufferedReader br = new BufferedReader(new InputStreamReader(in)); 
String line = null; 
while ((line = br.readLine()) != null) {...} 

这里的BufferedReader试图读取线(由EOL终止),而是由工艺对象返回的InputStream中从未达到EOL用户输入一些东西到的OutputStream之前并按下回车键。这就是为什么提示信息“输入数字”没有出现。将读取方法更改为

is.read() != -1 

在while循环中将显示提示消息。那么问题是如何检测用户输入。当用户输入内容并回车时,数据位于OutputStream的缓冲区中。我们需要实现的是逻辑来“感知”OutputStream中的某些内容,并且它需要被写入并刷新。在我的情况下,我有一个SWT文本供用户输入数据,所以我在Text控件中添加了一个SWT.DefaultSelection事件监听器来响应键盘输入。然后我看到了正确的节目输出。

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”字符所以在技术上它不是一条线。所以使用缓冲读取器读取线将不会有帮助。这可能是该计划在那里停留很久的一个问题。