java.io.IOException:无法运行程序“”,..":java.io.IO异常:错误=2,没有这样的文件或目录

s4n0splo  于 2023-04-28  发布在  Java
关注(0)|答案(4)|浏览(303)

我需要从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!");
4uqofj5v

4uqofj5v1#

ProcessBuilder构造函数要求外部程序的每个参数是独立的(以数组或ListString s的形式)。你收到的第一条异常消息

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"

不是抱怨它可以找到一个名为/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

而不是

command.add("--convert-to pdf:'writer_pdf_Export' --outdir " + getDestinationDirectory(order) + " " + getInvoiceFilename() + ".fodt")

诸如此类,将每个参数拆分为自己对List.add的调用

command.add("--convert-to");
command.add("pdf:writer_pdf_Export");

command.add("--outdir");
command.add(getDestinationDirectory(order).toString());

command.add(getInvoiceFilename() + ".fodt");

请注意,“writer_pdf_Export”周围没有撇号,因为这些是shell元字符,当您构造一个数组传递给exec而没有中间shell时,这些字符是不需要的。

u1ehiz5o

u1ehiz5o2#

保持简单(Keep it simple)..

Process p = Runtime.getRuntime().exec("/usr/bin/libreoffice --headless --convert-to pdf:'writer_pdf_Export' --outdir "+ getDestinationDirectory(order)+" "+getInvoiceFilename()+".fodt");

完全……

Process process = null;
    try {
            process = Runtime.getRuntime().exec("/usr/bin/libreoffice --headless --convert-to pdf:'writer_pdf_Export' --outdir "+ getDestinationDirectory(order)+" "+getInvoiceFilename()+".fodt");
    } catch (IOException ex) {
        Logger.getLogger(Documents.class.getName()).log(Level.SEVERE, null, ex);
    }
    BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
    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);
    }
    br.close();
    System.out.println("Program terminated!");
a8jjtwal

a8jjtwal3#

我已经尝试了在这个线程中提出的每一个解决方案,它不工作。
在我的应用程序(java webapp在linux中使用TOMCAT)中,它只适用于创建一个shell脚本并执行该脚本。但是你必须把绝对路径放在脚本中,如果没有,它就不起作用($HOME不起作用)。此外,您可以向它传递参数。
示例:

Runtime.getRuntime().exec("/home/user/myscript.sh param1");
1wnzp6jl

1wnzp6jl4#

ProcessBuilder有时会因为长命令(带有大量参数的可执行路径)而变得不稳定。)。你能做的是,
假设命令字符串为String cmdString =“executableFilePath -param 1-param 2”
将此转换为Map
List cmdMap = Arrays.asList(cmdString.int(““);
将此cmdMap传递给ProcessBuilder。

相关问题