Swing, tail -f and threading

Discussion in 'Java' started by Frank D. Greco, May 29, 2004.

  1. I'm trying to capture the stdout (and stderr) of an external program
    and show the output in a Swing JTextArea.

    For most short-running things like 'grep', 'cat'..., its fairly
    straightforward. But I'm having a little bit of difficulty with
    programs that run for a long time, namely 'tail -f'.

    Since 'tail -f foo' basically runs until you kill it, I'm assuming
    I need to wrap my JTextArea extended component (which I call 'FileWatcher')
    with a Thread/Runnable. This should allow me to instantiate a bunch of
    them in a nice front end that watches a bunch of logfiles.

    But I'm having problems when the objects are put into a JFrame. Nothing
    is rendered properly (1.4.2)... actually the JFrame is blank. But I
    get the output correctly since I also write it out to stdout in my console.

    Anyone have any suggestions? Should I thread my component externally, i.e.,
    in my JFrame when I instantiate my FileWatcher or should I put the thread
    "inside" of it, i.e., right before I Process.exec() the external program?
    I've tried both but with the same result.

    Any tips or URL refs are appreciated.

    Frank G.
    +==========================================+
    | Crossroads Technologies Inc. |
    | www.CrossroadsTech dot com |
    | fgreco at REMOVE!cross!roads!tech!dot!com|
    +=========================================+
    Frank D. Greco, May 29, 2004
    #1
    1. Advertising

  2. Frank D. Greco

    Hung Huynh Guest

    "Frank D. Greco" <> wrote in message
    news:...
    > I'm trying to capture the stdout (and stderr) of an external program
    > and show the output in a Swing JTextArea.
    >
    > For most short-running things like 'grep', 'cat'..., its fairly
    > straightforward. But I'm having a little bit of difficulty with
    > programs that run for a long time, namely 'tail -f'.
    >
    > Since 'tail -f foo' basically runs until you kill it, I'm assuming
    > I need to wrap my JTextArea extended component (which I call

    'FileWatcher')
    > with a Thread/Runnable. This should allow me to instantiate a bunch of
    > them in a nice front end that watches a bunch of logfiles.
    >
    > But I'm having problems when the objects are put into a JFrame. Nothing
    > is rendered properly (1.4.2)... actually the JFrame is blank. But I
    > get the output correctly since I also write it out to stdout in my

    console.
    >
    > Anyone have any suggestions? Should I thread my component externally,

    i.e.,
    > in my JFrame when I instantiate my FileWatcher or should I put the thread
    > "inside" of it, i.e., right before I Process.exec() the external program?
    > I've tried both but with the same result.
    >
    > Any tips or URL refs are appreciated.
    >
    > Frank G.
    > +==========================================+
    > | Crossroads Technologies Inc. |
    > | www.CrossroadsTech dot com |
    > | fgreco at REMOVE!cross!roads!tech!dot!com|
    > +=========================================+


    Hi,

    The code that update your JTextArea when you have new data should be in the
    event thread, which must be used via SwingUtilities.invokeLater()

    SwingUtilities.invokeLater(new Runnable()
    {
    public void run()
    {
    // update your jtextarea here
    }
    });

    Hung-
    Hung Huynh, May 29, 2004
    #2
    1. Advertising

  3. "Hung Huynh" <> sez:

    >"Frank D. Greco" <> wrote in message
    >> I'm trying to capture the stdout (and stderr) of an external program
    >> and show the output in a Swing JTextArea.
    >>
    >> For most short-running things like 'grep', 'cat'..., its fairly
    >> straightforward. But I'm having a little bit of difficulty with
    >> programs that run for a long time, namely 'tail -f'.


    >The code that update your JTextArea when you have new data should be in the
    >event thread, which must be used via SwingUtilities.invokeLater()
    >
    >SwingUtilities.invokeLater(new Runnable()
    >{
    > public void run()
    > {
    > // update your jtextarea here
    > }
    >});



    I've tried this approach but with no luck. This is what I have:

    SwingUtilities.invokeLater(
    new Runnable() {
    public void run() {
    try{
    while ( (str = in.readLine()) != null ) {
    out.println(str); // debugging

    append(str);
    append("\n");

    setCaretPosition(getDocument().getLength());
    }

    } catch (IOException ix) {
    d.trace(1, "Cannot view output of Process stdout");
    }
    }
    }
    );

    The exec() seems to block when running "tail -f", so I thought the
    threading should wrap the exec(), but that doesn't work either.

    Any other suggestions are appreciated.

    Frank G.
    +==========================================+
    | Crossroads Technologies Inc. |
    | www.CrossroadsTech dot com |
    | fgreco at REMOVE!cross!roads!tech!dot!com|
    +=========================================+
    Frank D. Greco, Jun 2, 2004
    #3
  4. Frank D. Greco wrote:
    > I've tried this approach but with no luck. This is what I have:


    A couple of things:


    0. As mentioned a thousand times in this newsgroup, please provide
    complete (has a main(), compiles, runs), small source code, not
    snippets. On reason: See next point


    > The exec() seems to block when running "tail -f", so I thought the
    > threading should wrap the exec(), but that doesn't work either.


    1. You don't show the way you run exec(). It might well be that you
    block something there. You would at least have:

    - a thread to read from stdout of the external program

    - another thread to read from stderr of the external program
    (very popular to forget this)

    And if you provide input:

    - thread nbr. three, if you don't want to block your current
    thread

    Also:
    - possibly a waitFor() in your current thread so you get
    informed when the external program terminates.


    > SwingUtilities.invokeLater(
    > new Runnable() {
    > public void run() {
    > try{
    > while ( (str = in.readLine()) != null ) {
    > out.println(str); // debugging
    >
    > append(str);
    > append("\n");
    >
    > setCaretPosition(getDocument().getLength());
    > }
    >
    > } catch (IOException ix) {
    > d.trace(1, "Cannot view output of Process stdout");
    > }
    > }
    > }
    > );


    2. This is doomed to block the EDT. What you are in fact doing is you
    schedule one callback on the EDT (your Runnable). The run() method gets
    at some point in time executed on the EDT. So your while() loop starts
    running in the EDT. You while() loop runs "endlessly", effectively
    blocking the EDT for every.

    class TextAreaUpdater implements Runnable {
    JTextArea ta;
    String line;

    public TextAreaUpdater(JTextArea ta, String line) {
    this.ta = ta;
    this.line = line;
    }

    public void run() {
    ta.append(line);
    :
    Thomas Weidenfeller, Jun 2, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Big Daddy

    Java 1.2 Swing vs. Java 1.5 Swing

    Big Daddy, Apr 15, 2005, in forum: Java
    Replies:
    2
    Views:
    495
    Pete Barrett
    Apr 16, 2005
  2. mkrause
    Replies:
    0
    Views:
    669
    mkrause
    May 6, 2005
  3. lizard
    Replies:
    0
    Views:
    1,759
    lizard
    Jan 30, 2006
  4. S.T
    Replies:
    2
    Views:
    574
  5. Terry Michaels

    Tail Call Optimization (Tail Recursion)

    Terry Michaels, Apr 18, 2011, in forum: Ruby
    Replies:
    16
    Views:
    309
    Robert Klemme
    Apr 20, 2011
Loading...

Share This Page