0

I am running the following code, and it stops at waitfor() function. What could be the reason and how can I solve it?

String line;
Process albumProcess;
try {
  albumProcess = Runtime.getRuntime().exec(
    "iconv -f UTF-16 -t UTF-8 /home/gozenem/"+ xmlFileName +
    ".xml | grep albumID");
  albumProcess.waitFor();
  BufferedReader in = new BufferedReader(
      new InputStreamReader(albumProcess.getInputStream()));
  ArrayList<String> lineList = new ArrayList<String>(); 
  while ((line = in.readLine()) != null) {  
    lineList.add(line);
  }
  result[0] = lineList.size();
  albumProcess.destroy();

} catch (Exception e) {}

2 Answers 2

2

The | grep ... is not consuming the output from the command as you expect because getRuntime().exec does not understand piping symbols. The process gets bogged down waiting for something to consume its output and its getting passed bogus command line arguments "|", "grep", and "albumId".

A shell will understand | but execv will not, so you need to use bash -c instead to get a shell to do the piping (see java shell for executing/coordinating processes? do the piping yourself (see Pipe between java processes on command shell not reliable working). Java 7 has a new ProcessBuilder class that makes it easy to set up pipes so you can use those if you're only running on a bleeding edge JVM.

Once you've got grep running, if there's a bunch of lines that match, it may still fill up the buffer, so you need something sitting on the buffer consuming the process's output stream. Moving

albumProcess.waitFor();

after the while loop should do it.

Sign up to request clarification or add additional context in comments.

7 Comments

How can i use bash -e ? I am new about this and it would be great if you help me. thank you.
@prgrmmr, bash -c "foo" starts a new shell that runs the command "foo" then exits. bash -c "foo | bar" includes piping. So just quote your command properly and put bash -c in front. From the manpage: "-c string If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0."
Processes don't typically hang around waiting for their output to be consumed, do they? Won't it just write to the stdout stream and exit? The process must be hanging for some other reason.
@chesles, Yes they do. Writes to stdout are blocking once the buffer fills up. The process's stdout is not linked to the parent's process's stdout unless the process was spawned in a way to inherit file descriptors. With Java7 that's easy but no so easy with other versions. When you create a process in Java, you are responsible for providing what it needs on its stdin and closing that when nothing else is available and draining its stdout or closing it.
@Mike using exec("yes") is slightly misleading, since yes won't exit until killed, whether blocking or not. I did observe the blocking behavior using cat on a file larger than 65,536 bytes though. I assume that size would vary depending on the size of the buffer on different machines.
|
1

I think you should try to read the output from the process before waiting on it. Otherwise, if the command outputs to much then the buffer may get filled.

Have a look at this article which explains how to read from the process: http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.