Runtime.getRuntime.exec()挂起在不同情况下运行的同一命令

时间:2014-05-25 03:35:20

标签: java runtime.exec

当我使用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命令,它会产生正确的结果。因此,输入文件没有任何问题。

3 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

在黑暗中拍摄,但您是否尝试使用catdoc标记在您的过程中运行-b命令?

  

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

答案 2 :(得分:0)

我已经在这里和其他地方尝试过所有提议的解决方案,但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();
}

此代码适用于不同类型的命令(短或长)和不同大小的文件(大或小)。我的问题彻底解决了。