Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中,为什么可以';我是否将超过94个字符的调用字符串传递给Runtime.getRuntime().exec()?_Java_Batch File_Runtime.exec - Fatal编程技术网

在Java中,为什么可以';我是否将超过94个字符的调用字符串传递给Runtime.getRuntime().exec()?

在Java中,为什么可以';我是否将超过94个字符的调用字符串传递给Runtime.getRuntime().exec()?,java,batch-file,runtime.exec,Java,Batch File,Runtime.exec,我正在尝试从java应用程序调用.bat文件。看起来很简单,但我有两个问题,非常感谢你的建议: 下面的代码无法执行bat文件,因为参数字符串超过94个字符。如果我恰好使用了94个字符(通过从clientArgs字符串末尾删除尾随的“x”),则bat文件执行正常。 (如果使用替代调用并将参数作为String[]传递,则会出现相同的问题) 无论如何,我需要能够传递更长的命令字符串(~150个字符) 如果我修改clientArgs以不包含完整文件名,而只包含短名称(因为我指定的是工作目录),我会得到:

我正在尝试从java应用程序调用.bat文件。看起来很简单,但我有两个问题,非常感谢你的建议:

  • 下面的代码无法执行bat文件,因为参数字符串超过94个字符。如果我恰好使用了94个字符(通过从
    clientArgs
    字符串末尾删除尾随的“x”),则bat文件执行正常。
    (如果使用替代调用并将参数作为
    String[]
    传递,则会出现相同的问题)
    无论如何,我需要能够传递更长的命令字符串(~150个字符)

  • 如果我修改
    clientArgs
    以不包含完整文件名,而只包含短名称(因为我指定的是工作目录),我会得到:

    java.io.IOException:无法运行程序“client.bat”(在目录“C:\2\code\FlaFl\FlaFl-0.7-RC2”中):CreateProcess error=2,系统找不到指定的文件

  • 代码如下:

    public static void main(String[] args) {  
        String CMD_FILE_NAME = "client.bat"; //cmd or bat - still limit'n is 94 chars
        String cmdFileFolder= "C:/2/code/FlaFl/flafl-0.7-RC2/"; 
        File workingDir = new File(cmdFileFolder);
        String clientArgs = cmdFileFolder + 
             CMD_FILE_NAME + " -host name12.mycompanyname3.com -app hive"
             + "123456789 34x";  //95 chars fails. remove the x to get it to work
        System.out.println("length of invoc str is "+clientArgs.length());
        Process process=null;
        try {
             process = Runtime.getRuntime().exec(clientArgs,null,workingDir);
        } catch (IOException e) {
             System.out.println("exception "+e);
        }
        //sleep(2000);
        //if (process!=null)
        //    process.destroy();
    }
    

    交互模式下的命令行长度限制为126个字符

    这可能是您的问题的原因


    您可以创建一个
    .bat
    文件,然后运行它。

    Exec的Java文档建议

    ProcessBuilder.start()现在是使用修改过的环境启动流程的首选方法


    尝试使用以下代码:

    public static void main(String[] args) {
        String CMD_FILE_NAME = "client.bat"; // cmd or bat - still limit'n is 94
                                                // chars
        String cmdFileFolder = "C:/2/code/FlaFl/flafl-0.7-RC2/";
        File workingDir = new File(cmdFileFolder);
        String clientArgs = CMD_FILE_NAME
                + " -host name12.mycompanyname3.com -app hive"
                + "123456789 34x"; // 95 chars fails. remove the x to get it to
                                    // work
        System.out.println("length of invoc str is " + clientArgs.length());
        Process process = null;
        try {
            process = Runtime.getRuntime().exec(clientArgs, null, workingDir);
        } catch (IOException e) {
            System.out.println("exception " + e);
        }
        // sleep(2000);
        // if (process!=null)
        // process.destroy();
    }
    

    当您将
    workingDir
    传递给
    Runtime.exec()
    方法时,您在命令中给出了
    cmdFileFolder
    ,即代码中的工作目录。

    尝试复制您的问题,我成功地运行了参数行更长的命令。
    试着插入

      try {
            p.waitFor();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
    执行命令(代替那些注释的
    sleep()…
    )后,确保允许它完成

    实际上,这种方法还有另一个问题(我最初认为这可能是您的问题)——如果您的进程写入足够的数据来填充其控制台缓冲区,它可能会阻塞,如下所述(javadoc for process):

    因为某些本机平台仅为提供有限的缓冲区大小 标准输入和输出流,未能及时写入输入 流或读取子流程的输出流可能会导致 子进程阻塞,甚至死锁

    所以你应该先读一读:

    InputStream is=process.getInputStream();
    BufferedReader br= new BufferedReader(new InputStreamReader(is));
    
    String line=new String();
    while ((line=br.readLine())!=null) System.out.println (line);  //do something real here
    
    如果您不想读取bat输出(我看您不想读取),您可以跳过所有这些,只需在单独的窗口中运行命令:
    cmd/c start\'my command\'c:/temp/startup.bat args


    (注意关于第二个带有工作目录的表单,使用
    cmd/c startup.bat参数
    来消除“未找到”异常)

    如果用数字替换最后的
    x
    (比如
    5
    )会怎么样<代码>:)您确定批处理文件在dir
    C:\2\code\FlaFl\FlaFl-0.7-RC2中吗?批处理文件在那里。为了确保这一点,我从eclipse控制台复制了该目录,并对其进行了DIR,我可以在那里看到它。顺便说一句,我的批处理文件只包含一行:在执行java代码后,我查看foo.txt,以查看我发送给它的参数是否附加到foo.txt。这是我决定它是运行还是不运行的方式,但我不想修改已启动进程的环境,感谢您提供了非常丰富的响应。您是否尝试过像我上面描述的那样使用echo语句调用bat文件?我注意到它对某些命令起作用,但由于某种原因对echo不起作用。回应您的一些评论:1)echo不等待输入,因此没有理由打开输入流。2) 我不想等待进程完成-我需要在几秒钟后终止它(我的问题是调用立即失败3)调用Cmd而不是指定.bat文件名是必须的还是更好?是的,我使用exact
    echo%*
    运行它。一旦它开始写入控制台(命令被回送到控制台),它就会失败(如果您不读取它)。尝试使用
    @echo
    或使用
    cmd/q/c
    调用。ad 1)这有点复杂,这个
    InputStream
    实际上是您的命令的输出。ad 2)确保它不写入标准输出-使用
    @echo off
    cmd/q
    或使用
    ProcessBuilder
    重定向其流。ad 3)这是我在不指定完整路径的情况下运行它的唯一方法。否则,我认为它们实际上是相等的(对cmd.exe调用参数的控制更少)