1

I'm running a command via runtime.exec which take some time. I want to update my ProgressBar while that.
I already get my desired systemoutput, the problem is: I get it all at once when the process is finished. And not step by step to update my ProgressBar ...

Here is some code

public Runtime rt = Runtime.getRuntime();
public Process pp;

  public doit() {
      try {
          pp = rt.exec(a_long_timed_process);
          InputStream is = pp.getErrorStream();
          InputStreamReader isr = new InputStreamReader(is);
          BufferedReader br = new BufferedReader(isr);
          String line = null;
          while ((line = br.readLine()) != null) {
              if (line.contains("In:")) {
                  int a = line.indexOf("In:");              //get a string
                  int b = line.lastIndexOf("%");            //between 
                  String lineout = line.substring(a + 3, b);//"0.00" and "99.99"
                  double nr = Double.parseDouble(lineout);  //make it a double
                  int round = (int) nr;                     //make it a usable int
                  System.out.println(round);
                  myProgressBar.setValue(round);            //UPDATE Progressbar
              }
          }
          pp.waitFor();
      } catch (IOException ex) {
          Logger.getLogger(Sox.class.getName()).log(Level.SEVERE, null, ex);
      } catch (InterruptedException ex) {
          Logger.getLogger(Sox.class.getName()).log(Level.SEVERE, null, ex);
      }
  }

every help is appreciated
Thanks in advance

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 1
    Don't block the EDT (Event Dispatch Thread) - the GUI will 'freeze' when that happens. Instead of calling `Thread.sleep(n)` implement a Swing `Timer` for repeating tasks or a `SwingWorker` for long running tasks. See [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) for more details. – Andrew Thompson Mar 08 '13 at 00:08

2 Answers2

3

You have to run the process in a different thread if you want to be able to process its output concurrently. A good way to do that is to use a ProcessBuilder.

From the documentation:

This class is used to create operating system processes.

[...]

Starting a new process which uses the default working directory and environment is easy:

Process p = new ProcessBuilder("myCommand", "myArg").start();

Here is an example that starts a process with a modified working directory and environment, and redirects standard output and error to be appended to a log file:

ProcessBuilder pb =
  new ProcessBuilder("myCommand", "myArg1", "myArg2");
Map<String, String> env = pb.environment();
env.put("VAR1", "myValue");
env.remove("OTHERVAR");
env.put("VAR2", env.get("VAR1") + "suffix");
pb.directory(new File("myDir"));
File log = new File("log");
pb.redirectErrorStream(true);
pb.redirectOutput(Redirect.appendTo(log));
Process p = pb.start();
assert pb.redirectInput() == Redirect.PIPE;
assert pb.redirectOutput().file() == log;
assert p.getInputStream().read() == -1;

See also here for another code example that you can adapt to your needs.

Community
  • 1
  • 1
Thomas
  • 17,016
  • 4
  • 46
  • 70
1

You are seeing the effect of output buffering in the started process. Nothing you can do about that in the Java code.

user207421
  • 305,947
  • 44
  • 307
  • 483