Question

I am trying to write a program that redirects System.out to a JTextArea (it doesn't have to be a JTextArea), but when I call System.out.println("Test!") the output to the text area is like so:

\n
st!
\n

The code for my OutputStream:

package gui;

import java.awt.*;
import java.io.*;
import javax.swing.text.*;

public class LogOutputStream extends OutputStream
{
    public void write(final int b) throws IOException
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                write0(b);
            }
        });
    }

    public void write(final byte[] b, final int off, final int len)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                write0(b, off, len);
            }
        });
    }

    public void write(final byte[] b)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                write0(b);
            }
        });
    }

    private void write0(int b)
    {
        Document doc = FernflowerGUI.frame.textArea.getDocument();
        try
        {
            doc.insertString(doc.getLength(), String.valueOf((char)b), null);
        }
        catch(BadLocationException impossible)
        {

        }
    }

    private void write0(byte[] b, int off, int len)
    {
        Document doc = FernflowerGUI.frame.textArea.getDocument();
        try
        {
            doc.insertString(doc.getLength(), new String(b, off, len), null);
        }
        catch(BadLocationException impossible)
        {

        }
    }

    private void write0(byte[] b)
    {
        write0(b, 0, b.length);
    }
}

The code that creates the PrintStream:

PrintStream ps = new PrintStream(new LogOutputStream(), true);

Can anyone please tell me what on Earth is going on?

Was it helpful?

Solution

Your code isn't thread-safe, basically.

You're accepting a synchronous call accepting a byte array - and then you're using that byte array later, and assuming it will still have the same content. What if the caller to write() overwrites the data in the byte array immediately after the method returns? By the time you get to use it, you won't have the right data.

I would extract the String from the byte array in your write call, and then use that String in the call to write0.

(I'd also personally use a Writer rather than an OutputStream - fundamentally you want to deal with text data, not binary data.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top