2

I am using library that has public void method init() with System.out.println() in it.

And in my implementation I can only access method init() which is void, but unable to get output from sout to my gui component JTextarea.

Is it possible to catch it (with InputStream or with some other way)?

Any help is appreciated.

thanks

Suzon
  • 749
  • 1
  • 8
  • 21
feruz
  • 53
  • 10

3 Answers3

4

Assuming you don't have access to the library and can change it (I would be somewhat suspicious of using a library that prints to System.out for a GUI app), you could do the following:

PrintStream oldOut = System.out;

try {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PrintStream newOut = new PrintStream(baos);

    System.setOut(newOut);

    OtherLib.init();

    textArea.setText(baos.toString());
} finally {
    System.setOut(oldOut);
}
beny23
  • 34,390
  • 5
  • 82
  • 85
  • Don't you hate it when you have the same answer and it's a 2 min difference? +1 for having a code example. And for using `ByteArrayOutputStream` cleverly (I didn't know about the `toString()` trick) – Nick Rippe Feb 25 '14 at 17:50
  • This is great, thanks beny23 and others! Though, is it possible to get output realtime? it is working/getting text to TextArea after operation is finished.. – feruz Feb 28 '14 at 05:04
2

If you want to get fancy, you can reroute System.Out to your own PrintStream using System.setOut(PrintStream out). At that point you can read that PrintStream using a InputStreamReader. That InputStreamReader can then populate your GUI.

This isn't exactly the recommended fashion of communicating within a JVM, but if that's what your library gives you, I guess that's what you have to work with.

But keep in mind, if you reroute System.Out, all methods using System.Out will use the new PrintStream. That means nothing will get printed to your console anymore.

Here's an example of what I'm talking about:

import java.io.*;
import java.util.Arrays;
import javax.swing.*;

public class StandardOutReader extends JPanel{

    JTextArea textArea = new JTextArea();

    public StandardOutReader(){
        add(textArea);

        try {
            //create all your inputs/outputs
            PipedOutputStream out = new PipedOutputStream();
            PipedInputStream in = new PipedInputStream(out);
            System.setOut(new PrintStream(out));
            final InputStreamReader reader = new InputStreamReader(in);


            //A thread that will continuously read the reader, and post the output to the GUI
            new Thread(new Runnable(){
                @Override
                public void run() {
                    try {
                        char[] cBuffer = new char[256]; //Buffer for reading
                        int bytesRead; // number of byts read in the last "read()" call
                        while((bytesRead = reader.read(cBuffer)) != -1){
                            //Copy over only the interesting bytes
                            final char[] copy = Arrays.copyOf(cBuffer, bytesRead);
                            //Tell the GUI to update
                            SwingUtilities.invokeLater(new Runnable(){
                                @Override
                                public void run() {
                                    textArea.append(new String(copy));
                                }});
                        }
                    }  catch (IOException e) {
                        e.printStackTrace();
                    }  finally{
                        //Closing the reader
                        try {
                            reader.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }}).start();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args){
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new StandardOutReader());
        frame.pack();
        frame.setSize(400, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        //Thread that randomly prints stuff.  Not part of the GUI stuff at all.
        new Thread(new Runnable(){
            @Override
            public void run() {
                for(int i = 0; i < 10; i++){
                    try {
                        Thread.sleep((long)(4000 * Math.random()));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Adding another phrase");
                }
            }}).start();
    }
}
Nick Rippe
  • 6,465
  • 14
  • 30
  • Hi Nick, is it possible to get it realtime? maybe using Swingworker or Listener. I found that there is addMessageListener(Listener ll, Event event), maybe this can be used to make it realtime?! thanks – feruz Feb 28 '14 at 08:04
  • @feruz You can have a thread (off of the EDT) sitting in a while loop, constantly reading from the `InputStreamReader`. As soon as it reads, it can publish to the GUI (using `SwingUtilities.invokeAndWait(...)`). Then everything will be as real-time as it can get. – Nick Rippe Feb 28 '14 at 14:07
  • Great, thanks... it is working, though I get exception: `java.io.IOException: Write end dead at java.io.PipedInputStream.read(PipedInputStream.java:311) at java.io.PipedInputStream.read(PipedInputStream.java:378) at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283) at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177) at java.io.InputStreamReader.read(InputStreamReader.java:184) at java.io.Reader.read(Reader.java:140)` – feruz Mar 01 '14 at 04:07
  • @feruz Yes, you'll get that exception because one end of the stream will always close before the other end. It should be safe to ignore that exception. – Nick Rippe Mar 03 '14 at 15:07
0

Due to some exception errors from other correct answers, I decided to look bit further and found following wonderful class, works flawlessly!

http://tips4java.wordpress.com/2008/11/08/message-console/

feruz
  • 53
  • 10