Spawned process output

R

rwfields

Attached is an example of how to grab stdout and stderr from a spawned
process. Comments are welcome.

Randall

/* Exec.java */

import java.io.IOException;

/** A example of spawning a process. */
public class Exec
{

public static void main (String[] args)
{
System.out.println("Hello world!");
String[] command = {
"C:/Sun/jdk1.5.0_06/bin/java.exe",
"HelloLog"
};
try
{
Process process = Runtime.getRuntime().exec(command);
StreamConsumer inFromProcess
= new StreamConsumer(process.getInputStream());
inFromProcess.start();
StreamConsumer errFromProcess
= new StreamConsumer(process.getErrorStream());
errFromProcess.start();
}
catch(IOException e)
{
e.printStackTrace();
}
}

}


/* StreamConsumer.java */

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.IOException;

public class StreamConsumer extends Thread
{
protected BufferedInputStream stream;
protected int bufSize = 1024;
protected byte[] buffer;

public StreamConsumer(InputStream stream)
{
this.stream = new BufferedInputStream(stream);
buffer = new byte[bufSize];
}

public void run()
{
boolean isDone = false;
while ( !isDone )
{
try
{
int count = stream.read(buffer, 0, bufSize);
String out = new String(buffer);
System.out.print(out);
if ( count < 0 )
{
isDone = true;
}
}
catch(IOException e)
{
isDone = true;
e.printStackTrace();
}
}
}

}


/* HelloLog.java */

import java.util.logging.Logger;

/** A class that prints something to stderr. */
public class HelloLog
{
private static final Logger log
= Logger.getLogger(HelloLog.class.getName());

public static void main (String[] args)
{
for ( int i = 0; i < 10; i++ )
{
log.info("Hello world!");
}
}

}
 
T

Thomas Weidenfeller

public class StreamConsumer extends Thread

public class StreamConsumer implements Runnable

BTW, the "consumer" does not consume the stream, but copies it to
standard out. Probably another class name would be better.

{
protected BufferedInputStream stream;
protected int bufSize = 1024;

protected static final int BUF_SIZE = 1024;
protected byte[] buffer;

Why delay the allocation of the buffer memory?

protected byte buffer[] = new byte[BUF_SIZE];
public StreamConsumer(InputStream stream)
{
this.stream = new BufferedInputStream(stream);
buffer = new byte[bufSize];

If you have an own buffer, there is no point in wrapping the stream in
an extra BufferedInputStream. One buffer is enough.
}

public void run()
{
boolean isDone = false;
while ( !isDone )
{
try
{
int count = stream.read(buffer, 0, bufSize);

BufferedInputStream.read() tries to avoid blocking by checking the
available() method of the underlying stream and returning early if there
is no data available. Depending on the behavior of the underlying
stream, you have just implemented a CPU-cycle burning while() loop.

[I have not checked the behavior of the streams returned by Process.
Maybe their available() methods always return available() == true, even
if no data is there, which would result in a blocking read()]

String out = new String(buffer);
System.out.print(out);

System.out is a PrintStream. You can directly copy the read bytes out,
without the need to convert to a String. See the write() method.

Also, if you use this for the output from a child process, you are
redirecting data from standard out and standard error from the child
process to standard out only. This breaks many useful applications.
if ( count < 0 )
{
isDone = true;
}
}
catch(IOException e)
{
isDone = true;
e.printStackTrace();
}
}

I would store the exception, so the creator of the thread could have a
look at it later.
/** A class that prints something to stderr. */

But which your code redirects to standard out.

/Thomas
 

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

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top