Problem logging to a JTextArea
Hi, I am trying to use java logging to write logging to the standard console and to a JTextArea component within the application. The program creates a new logger using a PipedOutputStream as the OutputStream, the console class starts another thread to listen to the corresponding PipedInputStream every 5 seconds and update the JTextArea, I am having two problems with it.
1. The standard console (System.err) is receiving the log message so I assume the log is being published in the StreamHandler but the PipedInputStream is not receiving anything, I also tried using ByteArrayOutputStream instead and still didnt receive anything.
2. i can only see how to replace the text in a textarea, is there a way to just add text.
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import java.util.logging.StreamHandler;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
publicclass MainTest
{
publicstaticvoid main( String[] args )
{
Logger userInfoLogger = Logger.getLogger(Main.class.getName());
userInfoLogger.addHandler(new StreamHandler (Console.getInstanceOf().getOutputStream(),new SimpleFormatter()));
userInfoLogger.severe("ExampleLogMessage");
JFrame frame =new JFrame();
frame.add(Console.getInstanceOf().getConsoleWindow());
frame.pack();
frame.setVisible(true);
}
}
/** Console provides information to user */
class Console
{
privatestatic Console console;
private JTextArea consoleWindow;
private PipedOutputStream baos;
private PipedInputStream bais;
private Console()
{
consoleWindow =new JTextArea(5,120);
consoleWindow.setAutoscrolls(true);
consoleWindow.setLineWrap(true);
consoleWindow.setEditable(false);
baos =new PipedOutputStream();
bais =new PipedInputStream();
try
{
baos.connect(bais);
}
catch(Exception e)
{
thrownew RuntimeException("Problem connecting error pipes");
}
startListening();
}
publicstatic Console getInstanceOf()
{
if(console==null)
{
console =new Console();
}
return console;
}
public OutputStream getOutputStream()
{
return baos;
}
public InputStream getInputStream()
{
return bais;
}
public JTextArea getConsoleWindow()
{
return consoleWindow;
}
privatevoid startListening()
{
Thread thread =new Thread()
{
publicvoid run()
{
while(true)
{
try
{
Thread.sleep(5000);
System.out.println("running test");
try
{
int i = Console.this.getInputStream().read();
System.out.println("Read"+i);
SwingUtilities.invokeLater(new Runnable()
{
publicvoid run()
{
Console.this.consoleWindow.setText("hello");
}
});
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
}
catch(InterruptedException ie)
{
ie.printStackTrace();
}
}
}
};
thread.start();
}
}
Thanks for the replies, the following code works although not sure its the best way of doing things, I had to extend Streamhandler to perform a flush() on the publish() method in order to get any data through to the input pipe, i also extended SimpleFormatter because I want every message to only be one line.
I also tried using a BufferedReader but it didnt work. I think it was because it was in a loop whereby either there was data in the pipe or there wasnt in which case it would stop, and it was tring to update the text area for every line, I just want it to update the text area once on every invocation with whatever is in the stream, and I need it to check throughout the lifetime of the program.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.MessageFormat;
import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import java.util.logging.StreamHandler;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class MainTest
{
public static void main( String[] args ) throws Exception
{
Logger userInfoLogger = Logger.getLogger(Main.class.getName());
userInfoLogger.addHandler(new GuiConsoleHandler (Console.getInstanceOf().getOutputStream(),new GuiConsoleFormatter()));
userInfoLogger.severe("ExampleLogMessage");
JFrame frame = new JFrame();
frame.add(Console.getInstanceOf().getConsoleWindow());
frame.pack();
frame.setVisible(true);
for(int i =0; i< 10;i++)
{
Thread.sleep(2000);
userInfoLogger.severe("ExampleLogMessage:"+i);
}
}
}
/** Console provides information to user */
class Console
{
private static Console console;
private JTextArea consoleWindow;
private PipedOutputStream baos;
private PipedInputStream bais;
private Console()
{
consoleWindow = new JTextArea(5,120);
consoleWindow.setAutoscrolls(true);
consoleWindow.setLineWrap(true);
consoleWindow.setEditable(false);
baos = new PipedOutputStream();
bais = new PipedInputStream();
try
{
baos.connect(bais);
}
catch(Exception e)
{
throw new RuntimeException("Problem connecting error pipes");
}
startListening();
}
public static Console getInstanceOf()
{
if(console==null)
{
console = new Console();
}
return console;
}
public OutputStream getOutputStream()
{
return baos;
}
public InputStream getInputStream()
{
return bais;
}
public JTextArea getConsoleWindow()
{
return consoleWindow;
}
private void startListening()
{
Thread thread = new Thread()
{
public void run()
{
try
{
while(true)
{
if(Console.this.getInputStream().available()>0)
{
byte[] vals = new byte[Console.this.getInputStream().available()];
Console.this.getInputStream().read(vals);
final String data = new String(vals);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
Console.this.consoleWindow.append(data);
}
catch(Exception e )
{
e.printStackTrace();
}
}
});
}
Thread.sleep(5000);
}
}
catch (Throwable _t)
{
_t.printStackTrace();
}
}
};
thread.start();
}
}
class GuiConsoleHandler extends StreamHandler
{
public GuiConsoleHandler(OutputStream out, Formatter formatter)
{
super(out,formatter);
}
public void publish( LogRecord record )
{
super.publish( record );
flush();
}
}
class GuiConsoleFormatter extends SimpleFormatter
{
private final static String format = "{0,date} {0,time}";
Date dat = new Date();
private Object args[] = new Object[1];
private MessageFormat formatter;
private String lineSeparator = (String) java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("line.separator"));
public synchronized String format(LogRecord record)
{
StringBuffer sb = new StringBuffer();
dat.setTime(record.getMillis());
args[0] = dat;
StringBuffer text = new StringBuffer();
formatter = new MessageFormat(format);
formatter.format(args, text, null);
sb.append(text);
sb.append(": ");
String message = formatMessage(record);
sb.append(record.getLevel().getLocalizedName());
sb.append(": ");
sb.append(message);
sb.append(lineSeparator);
if (record.getThrown() != null)
{
try
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
record.getThrown().printStackTrace(pw);
pw.close();
sb.append(sw.toString());
}
catch (Exception ex)
{
}
}
return sb.toString();
}