我的应用程序有很多System.out.println()语句。
我想从println捕获消息并将它们发送到标准记录器(Log4j,JUL等)。
怎么做?
答案 0 :(得分:35)
System类有一个setOut
和setErr
,可用于将输出流更改为,例如,带有支持PrintStream
的新File
或,在这种情况下,可能是另一个使用您选择的日志记录子系统的流。
请记住,如果您将日志记录库配置为输出到标准输出或错误(可能是无限递归类型),您可能会遇到麻烦。
如果是这种情况,您可能只想用真实的日志记录调用替换System.out.print
- 类型的语句。
答案 1 :(得分:30)
我曾经有类似的需求。我需要拦截某些第三方组件的输出并对错误消息做出反应。 这个概念看起来像这样:
private class Interceptor extends PrintStream
{
public Interceptor(OutputStream out)
{
super(out, true);
}
@Override
public void print(String s)
{//do what ever you like
super.print(s);
}
}
public static void main(String[] args)
{
PrintStream origOut = System.out;
PrintStream interceptor = new Interceptor(origOut);
System.setOut(interceptor);// just add the interceptor
}
答案 2 :(得分:9)
更好的解决方案是通过并更改所有println语句以使用正确的日志记录库。你要做的是一个大黑客。
答案 3 :(得分:2)
以下是如何将打印件捕获到System.out,然后按顺序重新打印:
var url = 'https://forward-byte-711.appspot.com/read/Test/Development/en';
$(function(){
$.getJSON(url, function(data){
$.each(data.paths,function(i,emp){
var b = this.places[0].place_position;
console.log(b);
});
});
});
答案 4 :(得分:2)
扩展PrintStream是一个糟糕的解决方案,因为您必须覆盖所有print()
和println()
方法。相反,您可以捕获流:
public class ConsoleInterceptor {
public interface Block {
void call() throws Exception;
}
public static String copyOut(Block block) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PrintStream printStream = new PrintStream(bos, true);
PrintStream oldStream = System.out;
System.setOut(printStream);
try {
block.call();
}
finally {
System.setOut(oldStream);
}
return bos.toString();
}
}
现在你可以像这样捕获它:
String result = ConsoleInterceptor.copyOut(() ->{
System.out.print("hello world");
System.out.print('!');
System.out.println();
System.out.println("foobar");
});
assertEquals("hello world!\nfoobar\n", result);
答案 5 :(得分:-1)
我应用了这个的基本想法,它工作得很好。 无需更改所有System.out。###和System.err。### stuff。
import java.io.OutputStream;
import java.io.PrintStream;
import de.msg.pm.designer.services.simulation.junit.base.Defines;
public class Interceptor extends PrintStream
{
/** the logger */
private Logger log;
/** the origin output stream */
PrintStream orig;
/**
* Initializes a new instance of the class Interceptor.
*
* @param out the output stream to be assigned
* @param log the logger
*/
public Interceptor( OutputStream out, Logger log )
{
super( out, true );
this.log = log;
}
/**
* {@inheritDoc}
*/
@Override
protected void finalize() throws Throwable
{
detachOut();
super.finalize();
}
/**
* {@inheritDoc}
*/
@Override
public void print( String s )
{
//do what ever you like
orig.print( s );
log.logO( s, true );
}
/**
* {@inheritDoc}
*/
@Override
public void println( String s )
{
print( s + Defines.LF_GEN );
}
/**
* Attaches System.out to interceptor.
*/
public void attachOut()
{
orig = System.out;
System.setOut( this );
}
/**
* Attaches System.err to interceptor.
*/
public void attachErr()
{
orig = System.err;
System.setErr( this );
}
/**
* Detaches System.out.
*/
public void detachOut()
{
if( null != orig )
{
System.setOut( orig );
}
}
/**
* Detaches System.err.
*/
public void detachErr()
{
if( null != orig )
{
System.setErr( orig );
}
}
}
public class InterceptionManager
{
/** out */
private Interceptor out;
/** err */
private Interceptor err;
/** log */
private Logger log;
/**
* Initializes a new instance of the class InterceptionManager.
*
* @param logFileName the log file name
* @param append the append flag
*/
public InterceptionManager( String logFileName, boolean append )
{
log = new Logger();
log.setLogFile( logFileName, append );
this.out = new Interceptor( System.out, log );
this.out.attachOut();
this.err = new Interceptor( System.err, log );
this.err.attachErr();
}
/**
* {@inheritDoc}
*/
@Override
protected void finalize() throws Throwable
{
if( null != log )
{
log.closeLogFile();
}
super.finalize();
}
}
这几行将启用日志记录而无需进一步更改代码:
if( writeLog )
{
this.logFileName = this.getClassName() + "_Log.txt";
this.icMan = new InterceptionManager( this.logFileName, false );
System.out.format( "Logging to '%s'\n", this.logFileName );
}