如何使用Java Process Builder执行需要多个输入的批处理脚本?

我有一个批处理脚本,它将输入作为用户名和年龄,并打印输入。 我想编写一个java程序来执行该脚本并传递输入。

我用ProcessBuilder编写了java程序。 我也在OutputStream过程中传递用户名和年龄,但只打印用户名并且缺少年龄。

我的脚本(test.bat文件):

@echo off echo executing test.bat set /p name=Enter Name: set /p age=Enter Age : echo Hi %name%, you are %age% years old. 

我的java程序:

 private static void executeInteractiveCommand(String cmd,String ... args){ try{ List command = new ArrayList(); command.add(cmd); ProcessBuilder builder = new ProcessBuilder(command); Map environ = builder.environment(); final Process process = builder.start(); OutputStream out = process.getOutputStream(); out.write("tester \n\r".getBytes()); out.flush(); out.write("25\n".getBytes()); out.flush(); out.close(); int errCode = process.waitFor(); System.out.println("Process Error Code : "+errCode); InputStream is = process.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line; while ((line = br.readLine()) != null) { System.out.println(line); } //out.close(); is.close(); System.out.println("Program terminated!"); }catch(IOException ex){ ex.printStackTrace(); } catch(InterruptedException ex){ ex.printStackTrace(); } } 

因此,您将两个输入分别刷新到批处理脚本并关闭流。 结果是脚本只消耗第一个输入。 然后,由于流被关闭,它将简单地清空所有剩余的SET /P语句,忽略管道中剩余的实际输入。 问题是:为什么?

我发现这篇文章分析了SET /P命令如何详细工作以及存在哪些条件以结束一个正在运行的输入提示会话。

最后2个读取字符是CRLF
这是正常情况和首选情况。 如果输入未通过管道输入但由用户键入,则输入在ENTER键被击中时完成。 然后设置CRLF令牌并消耗输入。 在我们的Java管道中,我们应该能够通过在String的末尾添加\r\n来做同样的事情。 但不知何故,这不起作用,我无法弄清楚为什么。

超时
我可以提供的一个非常简单的解决方法是在输入之间等待一段时间。 结果将是脚本在下一个之前消耗每个输入。 所以,如果你添加

 Thread.sleep(1000); 

你们两个输入之间的一切都会按预期工作。

完全缓冲
一个SET /P语句的输入限制为1024个字符。 我们可以使用它来通过管道一个小于1024的char的缓冲区来解决这种情况。所以下一个输入的第一个char将使缓冲区满,这将导致消耗输入并前进到下一个语句。 所以如果你使用这种转换方法

 public static byte[] convert(String str){ byte[] asBytes = str.getBytes(); byte[] result = new byte[1023]; for(int i = 0; i < asBytes.length; i++) result[i] = asBytes[i]; return result; } 

您的代码将按预期工作。 事实上,你甚至可以省去潮红。

 OutputStream out = process.getOutputStream(); out.write(convert("tester")); out.write(convert("25")); out.close(); 

你可以尝试下面的代码

 'Runtime runtime = Runtime.getRuntime(); Process proc = null; String executionarr[] = { batchfileName, arg1, arg2}; proc = runtime.exec(executionarr);' 

在批处理文件中,您可以使用%1读取第一个参数,使用%2读取第二个参数,依此类推。