Skip to content
Advertisement

How to redirect output from System.out to JavaFx TextArea

I’m trying to create a simple app that allows me to redirect all System.out to a JavaFX TextArea within my app.

For this, I created a CustomOutputStream class from the OutputStream class. Here’s the code for it:

//package name

//imports

public class CustomOutputStream extends OutputStream {
    private TextArea terminal;

    public CustomOutputStream(TextArea terminal) {
        this.terminal = terminal;
    }

    @Override
    public void write(int b) throws IOException {
        terminal.setText(terminal.getText() + String.valueOf((char) b));
    }
}

In my AppController.java file, I put TextArea as protected so I can access it from another class in the same package:

@FXML
protected static TextArea textArea_terminal;

Now this AppContoller.java, at the press of a button calls a function (runShell()) from another class. This function (runShell()) is the function that invokes another function of the Channel class whose output I’m hoping to put in the TextArea. As such, for this I implemented my CustomOutputStream this way:

PrintStream printStream = new PrintStream(new CustomOutputStream(AppController.textArea_terminal)) ;
System.setOut(printStream);

channel.setOutputStream(System.out); //channel is an instance of my class whose output I need.

Unfortunately, despite this, there is no output in the TextArea nor in the IDE terminal. And when I added System.out.println("hello") to test the printStream, a NullPointerException occured.

I’m thinking either there’s an issue with the way I pass the TextArea variable or perhaps an issue with the thread being occupied by my function in channel.

Any ideas why is this caused and how to resolve it?

Advertisement

Answer

I understand my issue is of a very specific nature and my question was perhaps too broad to convey that sufficiently.

My objective was to get the System.err messages from the output of the exec function in the JSch library and display it in a JavaFX TextArea. As such, I needed to get the error stream from a remote server, not the error stream of my local program.

I attempted to create an OutputStream to perform this but it didn’t solve my issue. As such, I figured out a workaround:

First I wrote the errors from the JSch channel (within which I run my exec fucntion) to a file:

File file = new File("tempOut/errorLog.txt");
FileOutputStream fos = new FileOutputStream(file);
PrintStream ps = new PrintStream(fos);
System.setErr(ps);
((ChannelExec) channel).setErrStream(System.err);

Then I read that file and display its contents in my GUI:

FileReader fileReader = new FileReader(file);    
BufferedReader br = new BufferedReader(fileReader);  //creates a buffering character input stream  
            
String line;
while ((line = br.readLine()) != null)
{ 
    terminalOut = textArea_terminalOut.getText();
    terminalOut = terminalOut + "nn" + line;
}

And that’s basically the workaround I figured out for this. If there’s a better way, I’d still appreciate it.

Advertisement