Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将sysout和syserr重定向到java中的自定义记录器?_Java_Logging - Fatal编程技术网

如何将sysout和syserr重定向到java中的自定义记录器?

如何将sysout和syserr重定向到java中的自定义记录器?,java,logging,Java,Logging,我有一个自定义记录器,我想将所有sysout和syserr从控制台重定向到该自定义记录器。因此,我想通过以下方式重定向sysout和syserr: 通过扩展ByteArrayOutputStream 然后设置System.setErr和System.setOut public class ServerLoggingPrintStream extends ByteArrayOutputStream { public ServerLoggingPrintStream() {

我有一个自定义记录器,我想将所有sysout和syserr从控制台重定向到该自定义记录器。因此,我想通过以下方式重定向sysout和syserr:

  • 通过扩展ByteArrayOutputStream
  • 然后设置System.setErr和System.setOut

    public class ServerLoggingPrintStream extends ByteArrayOutputStream  {
        public ServerLoggingPrintStream() {
            super();
        }
    
    public void write(byte[] originalBytes, int originalOffset, int originalLength) {
        synchronized(this) {
            String str = new String(originalBytes);
            if (str.length() == 0 || str.equals(System.getProperty("line.separator")) ) {
                        return;
            } 
    
            //using my custom logger named TRACE_LOGGER
            TRACE_LOGGER.log(LogLevel.INFO, this, "write", str);            
        }
      }
    }
    
    
    ServerLoggingPrintStream  serverLoggingPrintStreamStdOut_ = null;
    ServerLoggingPrintStream  serverLoggingPrintStreamStdErr_ = null;
    
    serverLoggingPrintStreamStdErr_ = new ServerLoggingPrintStream();
    System.setErr(new PrintStream(serverLoggingPrintStreamStdErr_));
    
    serverLoggingPrintStreamStdOut_ = new ServerLoggingPrintStream();
    System.setOut(new PrintStream(serverLoggingPrintStreamStdOut_));
    

你认为有更好的方法吗?

要把它做好比这更复杂。也就是说,有一些开源项目已经做到了这一点,所以您可以从那里借用一些代码。这里有一个例子:


我会使用一个OutputStream重定向到您使用的日志框架。它相当容易实现(我假设字符集是ISO的,所以编码时没有特别的处理):


这是它的要点,但是对于日志框架,细节可能会有所不同。主要的问题是,记录器通常希望记录字符串,而您从重定向流中获得原始的编码字节,因此您必须反转编码(在本例中,通过原始转换,技术上这应该使用读取器完成).

更好的方法是首先避免使用System.err和System.out。更好的方法是使用Java可用的众多健壮且经验证的日志框架之一,而不是使用自己的。例如,如果要使用
slf4j
,则存在一个。您使用的解决方案已经足够好了。已经有了一个日志框架。这个框架没有提供重定向sysout和syserr的方法。目前,我没有选择替换现有的日志框架。它是什么框架?嗨,这种方法的优势是什么?它通过实现一个流来收集数据,直到行馈送,然后将数据转发给日志记录器。关键是它需要最少的实现(通过直接从OutputStream继承,您已经为所有方法获得了正常工作的默认实现)。它和你的没有太大的不同,只是它覆盖了漏洞(有3种不同的写方法,你只实现了一种)。它比我提出的方法有什么优势?Hi Yishai,需要处理什么情况?@Baishak,你可以在链接上看到代码(或者寻找类的更高版本)。代码处理的一个问题是PrintStream希望您发送自己的新行,而日志框架通常不这样做,导致到处都是空行。我可以理解这一点。但我不明白的是,为什么他们需要使用ThreadLocalRecursiveCheck。我们可以检查是否有一个字符串,它是新行还是空行,我们就完成了。是吗?@baishak,我想象的递归检查是防御性的,以防注册码被调用两次(因此,当您传入当前System.out或System.err时,您实际上传入了这个类)。您必须测试您的实现,但是使用这样一个项目中的现有代码的优点是它经过了良好的测试。
final class RedirectionOutputStream extends OutputStream {

    StringBuilder buffer = new StringBuilder();

    @Override
    public synchronized void write(final int b) throws IOException {
        final char c = (char) (b & 0xFF);
        buffer.append(c);
        if (c == '\n') {
             // send buffered data to logging framework (its a complete line now)
             // reset buffer
             buffer.setLength(0);
        }
    }
}