[英]ProcessBuilder vs Runtime.exec()
I'm trying to create a frontend app in Java to handle batch SVG conversions using Inkscape's command line feature. 我正在尝试使用Inkscape的命令行功能在Java中创建一个前端应用程序来处理批量SVG转换。 I'm taking and updating the code from https://sourceforge.net/projects/conversionsvg/ .
我正在从https://sourceforge.net/projects/conversionsvg/获取并更新代码。 The way the original developer handled calling Inkscape by Runtime.getRuntime().exec(String) .
原始开发人员通过Runtime.getRuntime()。exec(String)处理Inkscape的方式。 The issue I'm running into is some inconsistencies between using methodA and methodB.
我遇到的问题是使用methodA和methodB之间存在一些不一致。 I created a simple java test project to demonstrate the different actions being performed.
我创建了一个简单的java测试项目来演示正在执行的不同操作。
CallerTest.java 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 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 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();
}
}
Result 结果
Both methodA(String) calls work, but when methodB(String[]) is called Inkscape is being started and the arguments are being passed incorrectly. 方法A(String)调用都有效,但是当调用methodB(String [])时,正在启动Inkscape并且参数传递不正确。 After methodB(String[]) executes I get an Inkscape error dialog for each saying
在执行methodB(String [])之后,我会为每个说法获取一个Inkscape错误对话框
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:\\ RuntimeExec-methodB.png
Failed to load the requested file -f C:/test.svg -D -w 100 -h 100 -e C:\\ProcessBuilder-methodB.png
无法加载请求的文件-f C:/test.svg -D -w 100 -h 100 -e C:\\ ProcessBuilder-methodB.png
and when I click Close on the dialog, Inkscape pops up with a new blank document. 当我在对话框中单击“关闭”时,Inkscape会弹出一个新的空白文档。 So, I guess I have a few questions:
所以,我想我有几个问题:
What is the difference between Runtime.getRuntime().exec(String) and Runtime.getRuntime().exec(String[])? Runtime.getRuntime()。exec(String)和Runtime.getRuntime()。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) ). JavaDoc说Runtime.exec(String)调用Runtime.exec(command,null) ( Runtime.exec(String cmd,String [] envp) ),后者又调用Runtime.exec(cmdarray,envp) (即运行时) .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?
所以,如果Runtime.getRuntime()。exec(String)正在调用Runtime.exec(String []) ,为什么我在使用不同的方法时会得到不同的结果?
Is something happening behind the scenes where Java sets up the environment differently depending on which method is called? 幕后发生的事情是Java根据调用的方法设置不同的环境吗?
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. 基本上,你将“
-f C:/test.svg -D -w 100 -h 100 -e C:\\RuntimeExec-methodB.png
”作为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"};
Roughly speaking, when you use Runtime.exec(String)
, the value you pass in gets evaluated by the shell, which parses out the argument list. 粗略地说,当您使用
Runtime.exec(String)
,传入的值将由shell进行评估,该shell将解析参数列表。 When you use Runtime.exec(String[])
, you're providing the argument list, so it doesn't need processing. 当您使用
Runtime.exec(String[])
,您将提供参数列表,因此不需要处理。 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. 这样做的好处是您不必转义shell特有的值,因为参数不会被它评估。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.