我需要从Java执行一个外部程序(使用libreoffice将 fodt 文件转换为 pdf,这是碰巧的)我知道程序所需的精确命令行:
/usr/bin/libreoffice --headless --convert-to pdf:'writer_pdf_Export' --outdir /home/develop/tomcat/mf/ROOT/private/docs/0/ /home/develop/tomcat/mf/ROOT/private/docs/0/35_invoice.fodt
这在命令行中运行得很好。但在Java中使用ProcessBuilder
时无法正常工作:
java.io.IOException: Cannot run program "/usr/bin/libreoffice --headless --convert-to pdf:'writer_pdf_Export' --outdir /home/develop/tomcat/mf/ROOT/private/docs/0 /home/develop/tomcat/mf/ROOT/private/docs/0/35_invoice.fodt": java.io.IOException: error=2, No such file or directory
我尝试了一些不同的方法,但没有成功。这是上次测试的样本
List<String> command = new ArrayList<String>();
command.add("/usr/bin/libreoffice");
command.add("--headless");
command.add("--convert-to pdf:'writer_pdf_Export' --outdir " + getDestinationDirectory(order) + " " + getInvoiceFilename() + ".fodt");
ProcessBuilder builder = new ProcessBuilder(command);
Process process = null;
try {
process = builder.start();
} catch (IOException ex) {
Logger.getLogger(Documents.class.getName()).log(Level.SEVERE, null, ex);
}
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
try {
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException ex) {
Logger.getLogger(Documents.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Program terminated!");
4条答案
按热度按时间4uqofj5v1#
ProcessBuilder
构造函数要求外部程序的每个参数是独立的(以数组或List
的String
s的形式)。你收到的第一条异常消息不是抱怨它可以找到一个名为
/usr/bin/libreoffice
的程序。它抱怨说它找不到一个具有非常长和特殊名称“/usr/bin/libreoffice --headless --convert-to pdf:'writer_pdf_Export' --outdir /home/develop/tomcat/mf/ROOT/private/docs/0 /home/develop/tomcat/mf/ROOT/private/docs/0/35_invoice.fodt
”的程序,因为你把参数连接成一个String
。而不是
诸如此类,将每个参数拆分为自己对
List.add
的调用请注意,“writer_pdf_Export”周围没有撇号,因为这些是shell元字符,当您构造一个数组传递给
exec
而没有中间shell时,这些字符是不需要的。u1ehiz5o2#
保持简单(Keep it simple)..
完全……
a8jjtwal3#
我已经尝试了在这个线程中提出的每一个解决方案,它不工作。
在我的应用程序(java webapp在linux中使用TOMCAT)中,它只适用于创建一个shell脚本并执行该脚本。但是你必须把绝对路径放在脚本中,如果没有,它就不起作用($HOME不起作用)。此外,您可以向它传递参数。
示例:
1wnzp6jl4#
ProcessBuilder有时会因为长命令(带有大量参数的可执行路径)而变得不稳定。)。你能做的是,
假设命令字符串为String cmdString =“executableFilePath -param 1-param 2”
将此转换为Map
List cmdMap = Arrays.asList(cmdString.int(““);
将此cmdMap传递给ProcessBuilder。