Log4J:如何将OutputStream或Writer重定向到logger的writer?

我有一个方法,它在启动后以异步方式运行,使用OutputStream或Writer作为参数。

它充当OutputStream或Writer的录制适配器( 它是我无法更改的第三方API )。

我怎么能将Log4J的内部OutputStream或Writer传递给该方法?
…因为Log4J吞下了System.out和System.err,我之前使用过。

我的建议是,为什么不编写OutputStream呢?! 我准备为你写一个,但我在网上找到了这个好例子,看看吧!

LogOutputStream.java

 /* * Jacareto Copyright (c) 2002-2005 * Applied Computer Science Research Group, Darmstadt University of * Technology, Institute of Mathematics & Computer Science, * Ludwigsburg University of Education, and Computer Based * Learning Research Group, Aachen University. All rights reserved. * * Jacareto is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * Jacareto is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with Jacareto; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ package jacareto.toolkit.log4j; import org.apache.log4j.Level; import org.apache.log4j.Logger; import java.io.OutputStream; /** * This class logs all bytes written to it as output stream with a specified logging level. * * @author Christian Spannagel * @version 1.0 */ public class LogOutputStream extends OutputStream { /** The logger where to log the written bytes. */ private Logger logger; /** The level. */ private Level level; /** The internal memory for the written bytes. */ private String mem; /** * Creates a new log output stream which logs bytes to the specified logger with the specified * level. * * @param logger the logger where to log the written bytes * @param level the level */ public LogOutputStream (Logger logger, Level level) { setLogger (logger); setLevel (level); mem = ""; } /** * Sets the logger where to log the bytes. * * @param logger the logger */ public void setLogger (Logger logger) { this.logger = logger; } /** * Returns the logger. * * @return DOCUMENT ME! */ public Logger getLogger () { return logger; } /** * Sets the logging level. * * @param level DOCUMENT ME! */ public void setLevel (Level level) { this.level = level; } /** * Returns the logging level. * * @return DOCUMENT ME! */ public Level getLevel () { return level; } /** * Writes a byte to the output stream. This method flushes automatically at the end of a line. * * @param b DOCUMENT ME! */ public void write (int b) { byte[] bytes = new byte[1]; bytes[0] = (byte) (b & 0xff); mem = mem + new String(bytes); if (mem.endsWith ("\n")) { mem = mem.substring (0, mem.length () - 1); flush (); } } /** * Flushes the output stream. */ public void flush () { logger.log (level, mem); mem = ""; } } 

资料来源: http : //sysgears.com/articles/how-to-redirect-stdout-and-stderr-writing-to-a-log4j-appender/

大段引用

Log4j不允许捕获stdout和stderr消息。 但是,如果您正在使用第三方组件并且必须记录它们刷新到流的消息,那么您可以执行一些技巧并实现支持日志记录的自定义输出流。

这已由Jim Moore完成(请参阅log4j源代码中的LoggingOutputStream)。 唯一的问题是JimMoore的LoggingOutputStream需要org.apache.log4j.Category和org.apache.log4j.Priority,现在已经部分弃用了。

这是修改后的LoggingOutputStream,它避免了不推荐使用的方法:

 public class LoggingOutputStream extends OutputStream { /** * Default number of bytes in the buffer. */ private static final int DEFAULT_BUFFER_LENGTH = 2048; /** * Indicates stream state. */ private boolean hasBeenClosed = false; /** * Internal buffer where data is stored. */ private byte[] buf; /** * The number of valid bytes in the buffer. */ private int count; /** * Remembers the size of the buffer. */ private int curBufLength; /** * The logger to write to. */ private Logger log; /** * The log level. */ private Level level; /** * Creates the Logging instance to flush to the given logger. * * @param log the Logger to write to * @param level the log level * @throws IllegalArgumentException in case if one of arguments * is null. */ public LoggingOutputStream(final Logger log, final Level level) throws IllegalArgumentException { if (log == null || level == null) { throw new IllegalArgumentException( "Logger or log level must be not null"); } this.log = log; this.level = level; curBufLength = DEFAULT_BUFFER_LENGTH; buf = new byte[curBufLength]; count = 0; } /** * Writes the specified byte to this output stream. * * @param b the byte to write * @throws IOException if an I/O error occurs. */ public void write(final int b) throws IOException { if (hasBeenClosed) { throw new IOException("The stream has been closed."); } // don't log nulls if (b == 0) { return; } // would this be writing past the buffer? if (count == curBufLength) { // grow the buffer final int newBufLength = curBufLength + DEFAULT_BUFFER_LENGTH; final byte[] newBuf = new byte[newBufLength]; System.arraycopy(buf, 0, newBuf, 0, curBufLength); buf = newBuf; curBufLength = newBufLength; } buf[count] = (byte) b; count++; } /** * Flushes this output stream and forces any buffered output * bytes to be written out. */ public void flush() { if (count == 0) { return; } final byte[] bytes = new byte[count]; System.arraycopy(buf, 0, bytes, 0, count); String str = new String(bytes); log.log(level, str); count = 0; } /** * Closes this output stream and releases any system resources * associated with this stream. */ public void close() { flush(); hasBeenClosed = true; } } 

现在,您可以通过以下方式捕获刷新到stderr或stdout的消息:

 System.setErr(new PrintStream(new LoggingOutputStream( Logger.getLogger("outLog"), Level.ERROR))); 

log4j.properties配置:

 log4j.logger.outLog=error, out_log log4j.appender.out_log=org.apache.log4j.RollingFileAppender log4j.appender.out_log.file=/logs/error.log log4j.appender.out_log.MaxFileSize=10MB log4j.appender.out_log.threshold=error 

Dmitriy Pavlenko,SysGears

大段引用

由于前一个针对Log4J的Writer的例子已经死了: http : //www.opensource.apple.com/source/JBoss/JBoss-737/jboss-all/common/src/main/org/jboss/logging/ UTIL / LoggerWriter.java