问题
I'm having an interesting problem when I use Runtime.getRuntime.exec() to run a command from Java. The following part of my code basically converts doc file to txt file. catdoc is a tool that converts input file to text stream and outputs it to the standard output. The ouput than redirected to a txt file. It works perfectly fine for some document files, however it hangs for some certain document files.
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();
I have many document files and this code segment works on some of the files but it hangs on one of the files and doesn't respond. I doubt that this may be cause by the size of the document file. Is that possible? I was wondering if there is any way that I could solve this problem.
Update: I know which files causes runtime to freeze. I tried using the catdoc command on those files, it produces correct result. So, nothing is wrong with the input files.
回答1:
If you call Process.waitFor()
before consuming all the output, the process can block trying to produce it. Move the waitFor()
after the reading code.
回答2:
Shot in the dark, but have you tried running the catdoc
command in your process with the -b
flag?
-b - process broken MS-Word file. Normally, catdoc checks if first 8 bytes of file is Microsoft OLE signature. If so, it processes file, otherwise it just copies it to stdin. It is intended to use catdoc as filter for viewing all files with .doc extension.
回答3:
I've tried all the proposed solutions here and other places but there was no help for Runtime.exec(). It seems, this is an internal buffer size problem in Runtime command. I found the same problem that runtime.exec() hangs. The problem was clearly described in the java docs which I just learned.
“Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.”
Therefore, I decided to use ProcessBuilder instead of Runtime. It completely solved my problem. Below is the code I used for my problem:
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();
}
This code works perfectly fine with different type of commands (short or long) and on different size of files (large or small). My problem is completely solved.
来源:https://stackoverflow.com/questions/23851745/runtime-getruntime-exec-hangs-on-same-command-that-it-runs-in-different-situat