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

时间:2016-10-07 09:02:48

标签: java processbuilder

我有一个批处理脚本,它将输入作为用户名和年龄并打印输入。我想编写一个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<String> command = new ArrayList<String>();
        command.add(cmd);
        ProcessBuilder builder = new ProcessBuilder(command);
        Map<String, String> 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();
            }
        }

2 个答案:

答案 0 :(得分:2)

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

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

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

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

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();

答案 1 :(得分:0)

你可以尝试下面的代码

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

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