How to read unbuffered stdout of a new process?

U

uljanow

hi,
is there a way to read directly from stdout of a process? I guess my
problem is that I'm using InputStreams, but I haven't found another
way.

ProcessBuilder builder = new ProcessBuilder("tail", "-f", "foo.log");
Process child = builder.start();
Scanner s = new Scanner(child.getInputStream()).useDelimiter("\\n");

while (!interrupted && s.hasNext())
log.append(s.nextLine() + "\n");

The problem with the code example is that the output of tail appears
after a buffer is filled. The log variable (JTextArea) appends the
string immediately.

Regards
 
G

Gordon Beaton

The problem with the code example is that the output of tail appears
after a buffer is filled. The log variable (JTextArea) appends the
string immediately.

Any delay you experience is due to the child process, which buffers
its output. Also, tail -f does not react immediately to changes in the
file it's monitoring (e.g. GNU tail waits 1 second between updates by
default).

You could implement tail -f in Java and avoid the issue altogether.

/gordon

--
 
R

Roedy Green

The problem with the code example is that the output of tail appears
after a buffer is filled. The log variable (JTextArea) appends the
string immediately.
If you can modify the child code, turn off any System.err and
System.out buffering, and do .flush periodically to send the output
off to the waiting mother task.
 
L

Larry Barowski

uljanow said:
hi,
is there a way to read directly from stdout of a process? I guess my
problem is that I'm using InputStreams, but I haven't found another
way.

ProcessBuilder builder = new ProcessBuilder("tail", "-f", "foo.log");
Process child = builder.start();
Scanner s = new Scanner(child.getInputStream()).useDelimiter("\\n");

while (!interrupted && s.hasNext())
log.append(s.nextLine() + "\n");

The problem with the code example is that the output of tail appears
after a buffer is filled. The log variable (JTextArea) appends the
string immediately.

To add to the previous responses, many command line programs
will buffer output when they are connected to a pipe, but not
when connected to a terminal or console. This makes it
difficult to run an interactive program through a Java launcher
program that provides the I/O as, for example, an IDE might do.

In UNIX/Linux, you can insert a native program between Java
and the target that connects to the target using a pty, and feeds
the target's output to the Java program as soon as it gets it. The
"wedge" code that is distributed with jGRASP provides that
function (and others) and is free of license restrictions. On
Windows, the situation is more difficult. There is no
"pseudoconsole". You can sort-of build one on NT/XP by
running the target in debug mode and intercepting console
writes, but it is difficult to distinguish input from output, and
you have to give up if there is any "cursor movement". I used
Gordon Chaffee's Windows port of "Expect" as a guide for
building such a program.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top