如何使用 Java Process Builder 执行接受多个输入的批处理脚本? [英] How to execute batch script which takes multiple inputs by using Java Process Builder?

查看:121
本文介绍了如何使用 Java Process Builder 执行接受多个输入的批处理脚本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a batch script which takes input as user name and age and prints both the inputs. I want to write a java program to execute that script and pass the inputs.

我已经使用 ProcessBuilder 编写了 java 程序.我还在进程 OutputStream 中传递了用户名和年龄,但只有用户名被打印并且年龄丢失.

I have written the java program using ProcessBuilder. I am also passing the username and age in the process OutputStream but only user name is getting printed and age is missing.

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

my script(test.bat file) :

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

推荐答案

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

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

So you flush two inputs separately to your batch script and close the stream. The result is that the script only consumes the first input. And since the stream is closed then, it will simply empty return all remaining SET /P statements ignoring the real inputs left in the pipe. And the question is: Why?

I found this article that analyses how the SET /P command works in detail and which conditions exists to end up one running input prompt session.

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

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

The last 2 read char are CRLF
This is the normal case and the prefered one. If input is not piped but typed by the user the input is finished when the ENTER key was hitten. Then the CRLF tokens were set and the input gets consumed. In our Java pipe we should be able to do the same by adding \r\n at the end of String. But somehow this doesn't work and I could not figure out why.

A timeout
A very simple workaround I could provide you is to simply wait some time between the inputs. The result will be that the script consumes each input before the next. So if you add

Thread.sleep(1000);

在您的两个输入之间,一切都会按预期工作.

完整缓冲区
一个 SET/P 语句的输入限制为 1024 个字符.我们可以使用它来解决这种情况,通过管道传输一个比 1024 小一个字符的缓冲区.因此,下一个输入的第一个字符将使缓冲区满,这将导致消耗输入并继续执行下一个语句.所以如果你使用这种转换方法

between you two inputs everything will work as expected.

full buffer
The input of one SET /P statement is limited to 1024 chars. We can use this to solve the situation by piping a buffer that is one char smaller than 1024. So the first char of the next input will make the buffer full which will result in consuming the input and going forward to the next statement. So if you use this convert method

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;
}

您的代码将按预期工作.事实上,你甚至可以省去冲洗.

Your code will work as expected. In fact you can even leave out the flushing.

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

这篇关于如何使用 Java Process Builder 执行接受多个输入的批处理脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆