ProcessBuilder与Runtime.exec() [英] ProcessBuilder vs Runtime.exec()

查看:96
本文介绍了ProcessBuilder与Runtime.exec()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Java创建一个前端应用程序,以使用Inkscape的命令行功能来处理批处理SVG转换.我正在从 https://sourceforge.net/projects/conversionsvg/中获取并更新代码.原始开发人员处理通过 Runtime.getRuntime().exec(String)调用Inkscape的方式.我遇到的问题是在使用methodA和methodB之间存在一些不一致之处.我创建了一个简单的Java测试项目,以演示正在执行的不同操作.

I'm trying to create a frontend app in Java to handle batch SVG conversions using Inkscape's command line feature. I'm taking and updating the code from https://sourceforge.net/projects/conversionsvg/. The way the original developer handled calling Inkscape by Runtime.getRuntime().exec(String). The issue I'm running into is some inconsistencies between using methodA and methodB. I created a simple java test project to demonstrate the different actions being performed.

CallerTest.java

package conversion;

import java.io.IOException;

public class CallerTest {

    static String pathToInkscape = "\"C:\\Program Files\\Inkscape\\inkscape.exe\"";  

    public static void main(String[] args) {

      ProcessBuilderCaller processBuilder = new ProcessBuilderCaller();
      RuntimeExecCaller runtimeExec = new RuntimeExecCaller();

      // methodA() uses one long command line string
      try {

        String oneLongString_ProcessBuilder = pathToInkscape + " -f \"C:\\test.svg\" -D -w 100 -h 100 -e \"C:\\ProcessBuilder-methodB.png\"";
        String oneLongString_RuntimeExec =    pathToInkscape + " -f \"C:\\test.svg\" -D -w 100 -h 100 -e \"C:\\RuntimeExec-methodA.png\"";

//        processBuilder.methodA(oneLongString_ProcessBuilder);
        runtimeExec.methodA(oneLongString_RuntimeExec);

      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

      // methodB() uses an array containing the command and the options to pass to the command
      try {

        String[] commandAndOptions_ProcessBuilder = {pathToInkscape, " -f \"C:/test.svg\" -D -w 100 -h 100 -e \"C:\\ProcessBuilder-methodB.png\""};
        String[] commandAndOptions_RuntimeExec =    {pathToInkscape, " -f \"C:/test.svg\" -D -w 100 -h 100 -e \"C:\\RuntimeExec-methodB.png\""};

        processBuilder.methodB(commandAndOptions_ProcessBuilder);
//        runtimeExec.methodB(commandAndOptions_RuntimeExec);

      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
}

RuntimeExecCaller.java

package conversion;

import java.io.IOException;

public class RuntimeExecCaller {
    Process process;

    // use one string
    public void methodA(String oneLongString) throws IOException {
      process = Runtime.getRuntime().exec(oneLongString);
    }

    // use the array
    public void methodB(String[] commandAndOptions) throws IOException {
      process = Runtime.getRuntime().exec(commandAndOptions);
    }
}

ProcessBuilderCaller.java

package conversion;

import java.io.IOException;

public class ProcessBuilderCaller {
    Process process;

    // use one string
    public void methodA(String oneLongString) throws IOException {
      process = new ProcessBuilder(oneLongString).start();
    }

    // use the array
    public void methodB(String[] commandAndOptions) throws IOException {
      process = new ProcessBuilder(commandAndOptions).start();
    }
}

结果

两个 methodA(String)都可以工作,但是调用 methodB(String [])时,Inkscape正在启动,并且参数传递不正确.在 methodB(String [])执行之后,我得到每个说法的Inkscape错误对话框

Both methodA(String) calls work, but when methodB(String[]) is called Inkscape is being started and the arguments are being passed incorrectly. After methodB(String[]) executes I get an Inkscape error dialog for each saying

无法加载请求的文件-f C:/test.svg -D -w 100 -h 100 -e C:\ RuntimeExec-methodB.png

Failed to load the requested file -f C:/test.svg -D -w 100 -h 100 -e C:\RuntimeExec-methodB.png

无法加载请求的文件-f C:/test.svg -D -w 100 -h 100 -e C:\ ProcessBuilder-methodB.png

Failed to load the requested file -f C:/test.svg -D -w 100 -h 100 -e C:\ProcessBuilder-methodB.png

,当我单击对话框上的关闭"时,Inkscape弹出并带有一个新的空白文档.所以,我想我有几个问题:

and when I click Close on the dialog, Inkscape pops up with a new blank document. So, I guess I have a few questions:

Runtime.getRuntime().exec(String)和Runtime.getRuntime().exec(String [])之间有什么区别?

What is the difference between Runtime.getRuntime().exec(String) and Runtime.getRuntime().exec(String[])?

JavaDoc说 Runtime.exec(String) 会调用 Runtime.exec(command,null)(这是 Runtime.exec(String cmd,String [] envp) ),它依次调用 Runtime.exec(cmdarray,envp)(即 Runtime.exec(String [] cmdarray,String [] envp) ).因此,如果 Runtime.getRuntime().exec(String)仍在调用 Runtime.exec(String []),为什么在使用不同的方法时会得到不同的结果?

JavaDoc says that Runtime.exec(String) calls Runtime.exec(command, null) (which is Runtime.exec(String cmd, String[] envp)) which in turn calls Runtime.exec(cmdarray, envp) (which is Runtime.exec(String[] cmdarray, String[] envp)). So, if Runtime.getRuntime().exec(String) is calling Runtime.exec(String[]) anyways, why am I getting different results when using different methods?

Java会根据调用哪种方法来不同地设置环境吗?

Is something happening behind the scenes where Java sets up the environment differently depending on which method is called?

推荐答案

我怀疑您的问题源于您指定参数列表的方式.本质上,您是将"-f C:/test.svg -D -w 100 -h 100 -e C:\RuntimeExec-methodB.png"作为一个单一参数传递给Inkscape.

I suspect your problem stems from the way you're specifying your argument list. Essentially, you're passing "-f C:/test.svg -D -w 100 -h 100 -e C:\RuntimeExec-methodB.png" as one single argument to Inkscape.

您需要做的是分别传递参数 ,例如:

What you need to do is pass the arguments individually, like so:

String[] commandAndOptions_ProcessBuilder = {pathToInkscape, "-f", "C:\\est.svg", "-D", "-w", "100", "-h", "100", "-e", "C:\\ProcessBuilder-methodB.png"};
String[] commandAndOptions_RuntimeExec = {pathToInkscape, "-f", "C:\\test.svg", "-D", "-w", "100", "-h", "100", "-e","C:\\RuntimeExec-methodB.png"};

粗略地说,当您使用Runtime.exec(String)时,传入的值将由外壳程序评估,该外壳程序将解析出参数列表.使用Runtime.exec(String[])时,将提供参数列表,因此不需要处理.这样做的好处是您不必转义shell专用的值,因为参数将不会被它评估.

Roughly speaking, when you use Runtime.exec(String), the value you pass in gets evaluated by the shell, which parses out the argument list. When you use Runtime.exec(String[]), you're providing the argument list, so it doesn't need processing. A benefit of doing this is that you don't have to escape values special to the shell, as the arguments will not be evaluated by it.

这篇关于ProcessBuilder与Runtime.exec()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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