重定向 System.out.println

发布于 2024-09-08 22:47:35 字数 106 浏览 11 评论 0原文

我的应用程序有许多 System.out.println() 语句。

我想从 println 捕获消息并将它们发送到标准记录器(Log4j、JUL 等)。

怎么办呢?

My application has many System.out.println() statements.

I want to catch messages from println and send them to the standard logger (Log4j, JUL etc).

How to do that ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

影子是时光的心 2024-09-15 22:47:35

System 类有一个 setOutsetErr 可用于将输出流更改为例如带有支持 < 的新 PrintStream code>File 或者,在本例中,可能是另一个使用您选择的日志子系统的流。


请记住,如果您将日志库配置为输出到标准输出或错误(可能是无限递归类型),您很可能会遇到麻烦。

如果是这种情况,您可能只想用真正的日志记录调用替换您的 System.out.print 类型语句。

The System class has a setOut and setErr that can be used to change the output stream to, for example, a new PrintStream with a backing File or, in this case, probably another stream which uses your logging subsystem of choice.


Keep in mind you may well get yourself into trouble if you ever configure your logging library to output to standard output or error (of the infinite recursion type, possibly).

If that's the case, you may want to just go and replace your System.out.print-type statements with real logging calls.

忱杏 2024-09-15 22:47:35

我曾经有过类似的需求。我需要拦截某些第三方组件的输出并对错误消息做出反应。
这个概念看起来像这样:

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
}

I had a similar need once. I needed to intercept the output of some 3rd party component and react on a error message.
The concept looks like this:

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
}
爺獨霸怡葒院 2024-09-15 22:47:35

更好的解决方案是检查并更改所有 println 语句以使用正确的日志记录库。你想做的是一个大黑客。

The better solution is to go through and change all the println statements to use a proper logging library. What you're trying to do is a big hack.

旧伤慢歌 2024-09-15 22:47:35

以下是如何将打印捕获到 System.out,然后将内容按顺序放回原处:

// Start capturing
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
System.setOut(new PrintStream(buffer));

// Run what is supposed to output something
...

// Stop capturing
System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));

// Use captured content
String content = buffer.toString();
buffer.reset();

Here is how to capture prints to System.out, and then put things back in order :

// Start capturing
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
System.setOut(new PrintStream(buffer));

// Run what is supposed to output something
...

// Stop capturing
System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));

// Use captured content
String content = buffer.toString();
buffer.reset();
风尘浪孓 2024-09-15 22:47:35

扩展 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);

extending PrintStream is a bad solution as you will have to override all print() and println() methods. Instead, you can capture the stream:

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();
    }
}

Now you can capture it like this:

   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);
谎言月老 2024-09-15 22:47:35

我应用了这个的基本思想并且效果很好。
无需更改所有 System.out.### 和 System.err.### 内容。

import java.io.OutputStream;
import java.io.PrintStream;   

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 )
  {
    logFileName = this.getClassName() + "_Log.txt";
    icMan = new InterceptionManager( logFileName, false );
    System.out.format( "Logging to '%s'\n", logFileName );
  }

I applied the base idea of this and it workes fine.
No need to change all the System.out.### and System.err.### stuff.

import java.io.OutputStream;
import java.io.PrintStream;   

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();
  }
}

This view lines will enable logging without further code changes:

  if( writeLog )
  {
    logFileName = this.getClassName() + "_Log.txt";
    icMan = new InterceptionManager( logFileName, false );
    System.out.format( "Logging to '%s'\n", logFileName );
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文