Reading STDERR from an input stream - TechRepublic
General discussion
February 24, 2004 at 02:27 PM
mariobjones

Reading STDERR from an input stream

by mariobjones . Updated 22 years, 1 month ago

An interesting challenge was presented a few days ago. My technical lead was developing a piece of software which used Java to wrap some business logic around a third party library written in C. The library was being hooked into our application via JNI (Java Native Interface). All worked well until the library had failures. From the JNI interface, we were able to make use of the return codes given by the function call to the library but more detailed information was being dumped to STDERR. We immediately thought, oh, let?s fire up the Runtime class and hook into a process stream and redirect STDOUT and STDERR, right? No. After an initial analysis, I found that Java didn’t provide a good way of redirecting STDERR or STDOUT.

I have provided a very simple way of redirecting STDERR to a readable input stream using an encapsulated class I?m calling Redir.

See listing below for the core class, Redir.java:

package com.slimdata.io;

import java.io.*;

/**
* Class used to demonstrate how one could redirect STDERR to a
* readable input stream.
*/
class Redir {

PipedInputStream pis;
PipedOutputStream pos;
PrintStream ps;
BufferedReader br;

final PrintStream stdErr = System.err;

public Redir() {
}

public void redirect() throws IOException {

pos = new PipedOutputStream();
pis = new PipedInputStream(pos);

br = new BufferedReader(new InputStreamReader(pis));
ps = new PrintStream(pos);

System.setErr(ps);
}

public String readLine() throws IOException {

String line = null;

if (br != null) {

line = br.readLine();
}

return line;
}

public void revert() {

System.setErr(stdErr);
}
}

See listing below for a sample user of the Redir class called RedirDriver:

package com.slimdata.io;

import java.io.*;
import java.util.*;

class RedirDriver {

public RedirDriver() {
}

public int myJniCall() {

String outString;

//fake a jni call that has errors
outString = “Error #65 – Application processing aborted.”;
System.err.println(outString);

return 5; //arbitrary value
}

public static void main(String[] args)
throws Exception {

int retCode;
String inString;

Redir redir = new Redir();

//pipe STDERR to an internal readable stream
redir.redirect();

//make my jni call
retCode = myJniCall();

if (retCode != 0) {

//read a line of data from STDERR
inString = redir.readLine();
System.out.println(“I read this from STDERR: ” + inString);
}
//send stream back to original STDERR
redir.revert();

//make my jni call again
retCode = myJniCall();

if (retCode != 0) {

//STDERR now goes to the java console
}
}
}

Conclusion

As I have tried to illustrate, for a task such as the one presented above, the need to read STDERR does exist in point applications and creating a simple to use lightweight class that encapsulates the inner-workings required to do so can be really simple. Using the Redir class, you can redirect and revert the STDERR stream as often as you like.

This class is really lightweight however remember nothing is free.

I hope that you may find use of this functionality and it can help in your software development tasks in the future.

Happy coding!

This discussion is locked

All Comments