【问题标题】:Runtime.getRuntime.exec() hangs on same command that it runs in different situationsRuntime.getRuntime.exec() 挂在它在不同情况下运行的同一命令上
【发布时间】:2014-05-25 03:35:19
【问题描述】:

当我使用 Runtime.getRuntime.exec() 从 Java 运行命令时,我遇到了一个有趣的问题。我的代码的以下部分基本上将 doc 文件转换为 txt 文件。 catdoc 是一个将输入文件转换为文本流并输出到标准输出的工具。输出比重定向到 txt 文件。它对于某些文档文件非常有效,但是对于某些特定文档文件它会挂起。

String[] strArr1 = new String[]{"catdoc", docFilePath};
Process p1= Runtime.getRuntime().exec(strArr1);
p1.waitFor();

BufferedReader b = new BufferedReader(new InputStreamReader(p1.getInputStream()));
FileWriter writeoutStream = new java.io.FileWriter(file.txt);

while ((line = b.readLine()) != null) {
    writeoutStream.write(line);
    writeoutStream.write('\n');
}
writeoutStream.close();
b.close();

我有许多文档文件,此代码段适用于某些文件,但它挂在其中一个文件上并且没有响应。我怀疑这可能是由文档文件的大小引起的。那可能吗?我想知道是否有什么方法可以解决这个问题。

更新:我知道哪些文件会导致运行时冻结。我尝试在这些文件上使用 catdoc 命令,它产生了正确的结果。所以,输入文件没有问题。

【问题讨论】:

  • 首先找到它挂起的文档,然后尝试仅在该文档上运行该命令以查找特定错误...无论如何我的猜测是它正在运行该命令的文档中没有'不存在
  • 我做到了。相同的命令运行并在终端中为 runtime.exec() 挂起的文件生成所需的结果。我会更新我的问题。
  • 'p1.getErrorStream()' 检查这个InputStream是否有错误
  • @fmodos 没有生成错误消息。基本上,程序挂了Process p1= Runtime.getRuntime().exec(strArr1);
  • 你能贴出没有运行的命令的 strArr1 值吗?数组中的值是什么?

标签: java runtime.exec


【解决方案1】:

如果您在使用所有输出之前调用Process.waitFor(),则该进程可能会阻止尝试生成它。将waitFor()移到读码后。

【讨论】:

    【解决方案2】:

    在黑暗中拍摄,但您是否尝试过在带有 -b 标志的进程中运行 catdoc 命令?

    -b - 处理损坏的 MS-Word 文件。通常,catdoc 检查文件的前 8 个字节是否为 Microsoft OLE 签名。如果是这样,它会处理文件, 否则它只是将其复制到标准输入。它旨在使用 catdoc 作为 用于查看所有带有 .doc 扩展名的文件的过滤器。

    【讨论】:

    • 我不认为它与 catdoc 有关。我在将 pdf 文件转换为 txt 文件时遇到了同样的问题。正如我在问题中提到的,我认为这与 Runtime.getRuntime.exec() 的内部有关。
    【解决方案3】:

    我已经在这里和其他地方尝试了所有建议的解决方案,但 Runtime.exec() 没有任何帮助。看来,这是运行时命令中的内部缓冲区大小问题。我发现 runtime.exec() 挂起的问题相同。这个问题在我刚学的java文档里有清楚的描述。

    “由于一些原生平台只为标准输入输出流提供有限的缓冲区大小,未能及时写入子进程的输入流或读取输出流可能会导致子进程阻塞,甚至死锁。”

    因此,我决定使用 ProcessBuilder 而不是 Runtime。它完全解决了我的问题。以下是我用于解决问题的代码:

    String[] strArr1 = new String[]{"catdoc", docFilePath};
    ProcessBuilder probuilder = new ProcessBuilder( strArr1 );
    Process process = probuilder.start();
    
    InputStream is = process.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    
    FileWriter writeoutStream = new java.io.FileWriter(file.txt);
    
    while ((line = br.readLine()) != null) {
        writeoutStream.write(line);
        writeoutStream.write('\n');
    }
    writeoutStream.close();
    br.close();
    isr.close();
    is.close();
    
    //Wait to get exit value
    try {
        int exitVal = process.waitFor();
        System.out.println("\n\nExit Value is " + exitVal);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    

    此代码在不同类型的命令(短或长)和不同大小的文件(大或小)上都能正常工作。我的问题完全解决了。

    【讨论】:

    • 您还需要在单独的线程中或通过合并流来使用标准错误流。
    • 我想你可能会感到困惑。 Runtime.exec()ProcessBuilder 之间的区别在于您在初始实现中拥有的 p1.waitFor();。那是造成您的问题的原因。如果将此添加到基于 ProcessBuilder 的实现中,您将遇到同样的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-06
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    • 2014-12-17
    • 1970-01-01
    • 2017-05-18
    相关资源
    最近更新 更多