0

I am trying to read the stdInput and stdError from a process while the process is running. I created a thread to run the process, and that works. In the constructor for the I pass a reference to a Process that is created so I can watch the output from the process. The problem is it does not seem to be linking the reference process leaving it set to null. The goal of all this is to be able to watch the output of the process while the process is still running, currently I am stuck with looking at the output after it is done. I figure this is due to the tread being run but I hope there is a way to do this.

    try { 
        Process p = null;
        Thread mythread =  new Thread( new SJ(pathF.getText(), fileF.getText(), p, view) ) ;
        mythread.start();
        BufferedReader stdInput = null;
        BufferedReader stdError = null;
        String s = null;
        stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
        stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
        while (mythread.isAlive()) { 
            while ((s = stdInput.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
            while ((s = stdError.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
        } 
    } catch ( IOException e ) {}



    class SJ implements Runnable {
        String Path = "";
        String File = "";
        public static viewering view;
        Process p = null;

        public SJ ( String arg1, String arg2, Process p1, viewering view )  {
            Path = arg1;
            File = arg2;
            p = p1;
        }

        public void run() {
            String[] command = new String[5];
            command[0] = "cmd";
            command[1] = "/C";
            command[2] = "compile";
            command[3] = Path;
            command[4] = File;

            BufferedReader stdInput = null;
            BufferedReader stdError = null;
            String s = null;
            try { 
                p = Runtime.getRuntime().exec( command, null, new File( "C:/Users/michael.b.goff/Documents/java/" ) );
                stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
                stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                while ((s = stdInput.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
                while ((s = stdError.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
            } catch ( IOException e ) {}
        }
    }

Here is the code for the final working scenario

public void actionPerformed(ActionEvent ae) {
    frame.setVisible( false );
    final Thread mythread =  new Thread( new SJ(pathF.getText(), fileF.getText(), view) ) ;
    mythread.start();
    final Timer ThreadTimer = new Timer( 1000, null );
    ThreadTimer.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (!mythread.isAlive()) {
                frame.setVisible( true );
                ThreadTimer.stop();
            }
    }});
    ThreadTimer.start();
}

class SJ implements Runnable {
    String Path = "";
    String File = "";
    public static viewering view;

    public SJ ( String arg1, String arg2, viewering view1 )  { 
        Path = arg1;
        File = arg2;
        view = view1;
    }

    public void run() {
        String[] command = new String[5];
        command[0] = "cmd";
        command[1] = "/C";
        command[2] = "compile";
        command[3] = Path;
        command[4] = File;

        BufferedReader stdInput = null;
        BufferedReader stdError = null;
        Process p = null;
        String s = null;
        try { 
            p = Runtime.getRuntime().exec( command, null, new File( "C:/Users/michael.b.goff/Documents/java/" ) );
            stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
            stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            while ((s = stdInput.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
            while ((s = stdError.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
        } catch ( IOException e ) {}
    }
}
Goff
  • 343
  • 1
  • 3
  • 14
  • p == null: You only pass p = null to the Runnable Contructor by value. Even if you create the Process in the runnable and assign the object to the p in your runnable the outer p remains null. This should throw a null pointer exception. – Peter Paul Kiefer May 19 '15 at 20:52
  • you dont need a Thread! you start an independent process. exec is not blocking. – Peter Paul Kiefer May 19 '15 at 20:53
  • I'm not sure what you are saying, I just tried p == p1; and Process p == null; both errored out saying that they are not commands. What should I do? – Goff May 19 '15 at 20:57
  • In regards to the "you dont need a Thread!" comment the output from the exec does not occur until the process is finished, I would like it to be realtime, or just a little slow. – Goff May 19 '15 at 20:58
  • Sorry, my answer was not clear. I used p==null to say that the variable outer p is assigned to null. Then you pass this null to your SJ Constructor in the variable p1. You assign p1 to the inner p (declared **in** the SJ object) with (p = p1;) In the run method you start the process. That creates a Process object for you wich is assigned to the inner p. The outer p is still null. I see no way to assigne to Process object to the outer p. When you use the outer p it is null. – Peter Paul Kiefer May 19 '15 at 21:16
  • You don't need a thread: Starting a process does not block you programm execution. If you get no output until the process is stopped then this must have another reason. Perhaps the compiler process buffers its output until it flushes at the end. Or the construct of wrapped BufferedReader/StreamReader blocks the output until it is flushed i.e. the process is stopped. – Peter Paul Kiefer May 19 '15 at 21:26
  • int the line "Thread mythread =" does that not pass a reference to p and not the value of p? it is passing the reference of view correctly and it is acting properly. "view.write( s + "\r\n" );" this statement works. Perhaps I can create p in another way? – Goff May 19 '15 at 21:29
  • ***Edit*** I would like to enter some details I just noticed. "System.out.println(s); view.write( s + "\r\n" );" the println happens near real time but the view.write does not. View is just a frame with the text field that acts like a console window. – Goff May 19 '15 at 21:36
  • Yes you assigned a pointer (null) to the parameter p1 and a pointer to the parameter view. Your code is not complete, so I can see what value view has. It may be not null then it works, because the outer view ist assigned to a value != null and the inner view holds the same pointer / object refrence. But the outer p will not change if an object refrence was assigned to the inner p . If you would initialize the outer view variable with null and intanciate the view in the Runnable that, won't work too. – Peter Paul Kiefer May 19 '15 at 21:42
  • Ok, I'm with you so far, I've tried "Process p = new Process();" but that fails because Process is abstract, I've tried googling a clean way of creating a new process but I didn't get useful info. Can you sugest a something better than "Process p = null;" ? – Goff May 19 '15 at 21:48
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/78256/discussion-between-peter-paul-kiefer-and-user1874355). – Peter Paul Kiefer May 19 '15 at 21:51
  • I tried to go to the chat but the security settings are too severe where I work, I can barely get this page to work 1 out of 4 times. – Goff May 19 '15 at 21:58
  • new Process() makes no sense, because the Process object is the control and information interface for a real process you startet with the operating system (resp. exec method in Java). Even if you create a Process object and assign it to the outer p, iut won't help. This object would initially be assigned to the inner object, but after the exec call the inner p was overwritten with Process object created by the exec method while the outer p still holds the object that you created at the beginning. You will not get access to the inner p. I suggest **not** using a Thread to read from the Streams. – Peter Paul Kiefer May 19 '15 at 22:07
  • Ok, I think I have found something that may be the cause of this issue but I don't know how to correct it. Swing has its own thread. The first part of the code is in a jbutton, the sequence takes a few minutes to run completely, since the jbutton is not finished the "view" component that also uses swing is being held up by the jbutton. Is there a way to return control to swing? With out "while (mythread.isAlive()) { " and its sub-components it will let "view" run at near real time. – Goff May 20 '15 at 16:25

1 Answers1

0

Ok, that's a completly different problem. And now I understand your real problem. If you excute the first part of your code in the click listener of a button, Swings event loop which is running in an own thread hangs for a while. Then you have to use a Thread. ;-)

Look at the last answer in this question: Printing a Java InputStream from a Process

Community
  • 1
  • 1
Peter Paul Kiefer
  • 2,114
  • 1
  • 11
  • 16
  • ok I have a working scenario I am posting the finished code so that others can use it to have a near real time swing console port. – Goff May 20 '15 at 20:32