【问题标题】:java.io.IOException: Cannot run program "...": java.io.IOException: error=2, No such file or directoryjava.io.IOException:无法运行程序“...”:java.io.IOException:错误=2,没有这样的文件或目录
【发布时间】:2020-10-12 21:52:48
【问题描述】:

我需要从 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

这在命令行中完美运行。 但它不适用于使用ProcessBuilder 的Java:

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!");

【问题讨论】:

  • 当您尝试移动的文件或目录不存在时,此错误很典型。您的命令可能是正确的,但是您的文件或路径没有到达另一端(例如路径)。
  • @ViniciusLima 这不是问题的原因。

标签: java


【解决方案1】:

ProcessBuilder 构造函数要求外部程序的每个参数是分开的 (以数组或ListStrings 的形式)。您收到的第一条异常消息,

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 元字符,当您在​​没有中间 shell 的情况下构造要传递给 exec 的数组时不需要撇号。

【讨论】:

  • 我的系统上没有任何 filters/writer_pdf_Export.xcu,但是如果我直接在 shell 中键入该命令,它就可以工作
  • 一分为二 (command.add("--convert-to"); command.add("pdf:writer_pdf_Export");) 导致 *Unknown 选项: --outdir *
  • @Azathoth,听起来我们正在取得进展,因为它抱怨后面的参数。您是否尝试过按照我上面的建议将每个参数拆分为自己的add?也许用您当前的代码更新您的问题会使诊断更容易。
【解决方案2】:

试试这个(保持简单)...

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!");

【讨论】:

  • 这是第一个测试:没有错误,没有输出,最重要的是......没有 pdf
  • 它可以从命令行工作吗?我找到了这个bugs.freedesktop.org/show_bug.cgi?id=44486
  • 当您同时读取进程InputStream 和进程ErrorStream 时,您是否得到相同的错误?见getInputStreamgetErrorStream
  • 你能cd到这里/home/develop/tomcat/mf/ROOT/private/docs/0吗?目录的权限是什么? ...和输出文件?
  • 是的,通过 shell 就像一个魅力。删除了下划线,但没有任何变化。我的用户有读/写权限,是的。实际上这个项目使用 netbeans+tomcat 在本地运行,并且属于同一个用户
【解决方案3】:

我已经尝试了这个帖子中提出的所有解决方案,但它不起作用。

在我的应用程序(在 linux 中使用 TOMCAT 的 java webapp)中,它只能创建一个 shell 脚本并执行该脚本。但是你得把绝对路径放在脚本里,不然不行($HOME不行)。此外,您可以传递参数。

例子:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-22
    • 2019-03-17
    • 1970-01-01
    • 2019-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多