java 将 System.out 和 System.err 重定向到 slf4j
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11187461/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Redirect System.out and System.err to slf4j
提问by itshorty
I needed to redirect System.out/err.println outputs to slf4j.
我需要将 System.out/err.println 输出重定向到 slf4j。
I know that this is not the way to do logging properlybut there is an external library, which logs to System.out
我知道这不是正确进行日志记录的方法,但是有一个外部库可以记录到 System.out
采纳答案by flavio.donze
You can use sysout-over-slf4j.
您可以使用sysout-over-slf4j。
The sysout-over-slf4j module allows a user to redirect all calls to System.out and System.err to an SLF4J defined logger with the name of the fully qualified class in which the System.out.println (or similar) call was made, at configurable levels.
sysout-over-slf4j 模块允许用户将所有对 System.out 和 System.err 的调用重定向到一个 SLF4J 定义的记录器,该记录器具有在其中进行 System.out.println(或类似)调用的完全限定类的名称, 在可配置的级别。
If you are notusing Maven, downloadthe jar and add it to your classpath.
如果您不使用 Maven,请下载jar 并将其添加到您的类路径中。
Alternatively, add it as a Maven dependency:
或者,将其添加为 Maven 依赖项:
<dependency>
<groupId>uk.org.lidalia</groupId>
<artifactId>sysout-over-slf4j</artifactId>
<version>1.0.2</version>
</dependency>
Then at application startup, call:
然后在应用程序启动时,调用:
SysOutOverSLF4J.sendSystemOutAndErrToSLF4J();
回答by itshorty
I solved the problem by using the LoggingOutputStreamfor log4j and modified it a little bit for slf4j.
我通过使用log4j的LoggingOutputStream解决了这个问题,并为 slf4j 修改了一点。
import java.io.IOException;
import java.io.PrintStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SysStreamsLogger {
private static Logger sysOutLogger = LoggerFactory.getLogger("SYSOUT");
private static Logger sysErrLogger = LoggerFactory.getLogger("SYSERR");
public static final PrintStream sysout = System.out;
public static final PrintStream syserr = System.err;
protected static final String LINE_SEPERATOR = System.getProperty("line.separator");
public static void bindSystemStreams() {
// Enable autoflush
System.setOut(new PrintStream(new LoggingOutputStream(sysOutLogger, false), true));
System.setErr(new PrintStream(new LoggingOutputStream(sysErrLogger, true), true));
}
public static void unbindSystemStreams() {
System.setOut(sysout);
System.setErr(syserr);
}
private static class LoggingOutputStream extends java.io.OutputStream {
protected Logger log;
protected boolean isError;
/**
* Used to maintain the contract of {@link #close()}.
*/
protected boolean hasBeenClosed = false;
/**
* The internal buffer where data is stored.
*/
protected byte[] buf;
/**
* The number of valid bytes in the buffer. This value is always in the
* range <tt>0</tt> through <tt>buf.length</tt>; elements
* <tt>buf[0]</tt> through <tt>buf[count-1]</tt> contain valid byte
* data.
*/
protected int count;
/**
* Remembers the size of the buffer for speed.
*/
private int bufLength;
/**
* The default number of bytes in the buffer. =2048
*/
public static final int DEFAULT_BUFFER_LENGTH = 2048;
private LoggingOutputStream() {
// illegal
}
/**
* Creates the LoggingOutputStream to flush to the given Category.
*
* @param log
* the Logger to write to
*
* @param isError
* the if true write to error, else info
*
* @exception IllegalArgumentException
* if cat == null or priority == null
*/
public LoggingOutputStream(Logger log, boolean isError) throws IllegalArgumentException {
if (log == null) {
throw new IllegalArgumentException("log == null");
}
this.isError = isError;
this.log = log;
bufLength = DEFAULT_BUFFER_LENGTH;
buf = new byte[DEFAULT_BUFFER_LENGTH];
count = 0;
}
/**
* Closes this output stream and releases any system resources
* associated with this stream. The general contract of
* <code>close</code> is that it closes the output stream. A closed
* stream cannot perform output operations and cannot be reopened.
*/
@Override
public void close() {
flush();
hasBeenClosed = true;
}
/**
* Writes the specified byte to this output stream. The general contract
* for <code>write</code> is that one byte is written to the output
* stream. The byte to be written is the eight low-order bits of the
* argument <code>b</code>. The 24 high-order bits of <code>b</code> are
* ignored.
*
* @param b
* the <code>byte</code> to write
*/
@Override
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 == bufLength) {
// grow the buffer
final int newBufLength = bufLength + DEFAULT_BUFFER_LENGTH;
final byte[] newBuf = new byte[newBufLength];
System.arraycopy(buf, 0, newBuf, 0, bufLength);
buf = newBuf;
bufLength = newBufLength;
}
buf[count] = (byte) b;
count++;
}
/**
* Flushes this output stream and forces any buffered output bytes to be
* written out. The general contract of <code>flush</code> is that
* calling it is an indication that, if any bytes previously written
* have been buffered by the implementation of the output stream, such
* bytes should immediately be written to their intended destination.
*/
@Override
public void flush() {
if (count == 0) {
return;
}
// don't print out blank lines; flushing from PrintStream puts out
// these
if (count == LINE_SEPERATOR.length()) {
if (((char) buf[0]) == LINE_SEPERATOR.charAt(0) && ((count == 1) || // <-
// Unix
// &
// Mac,
// ->
// Windows
((count == 2) && ((char) buf[1]) == LINE_SEPERATOR.charAt(1)))) {
reset();
return;
}
}
final byte[] theBytes = new byte[count];
System.arraycopy(buf, 0, theBytes, 0, count);
if (isError) {
log.error(new String(theBytes));
} else {
log.info(new String(theBytes));
}
reset();
}
private void reset() {
// not resetting the buffer -- assuming that if it grew that it
// will likely grow similarly again
count = 0;
}
}
}
Now it's possible to redirect Sytem.out/err by calling SysStreamsLogger.bindSystemStreams()
at the begining of your application.
现在可以通过SysStreamsLogger.bindSystemStreams()
在应用程序开始时调用来重定向 Sytem.out/err 。
Logging Output looks like this (from OpenEJB startup)
日志输出看起来像这样(来自 OpenEJB 启动)
2012-06-27 13:44:12,792 INFO [main:] SYSOUT:181 - Apache OpenEJB 3.1.4 build: 20101112-03:32
2012-06-27 13:44:12,793 INFO [main:] SYSOUT:181 - http://openejb.apache.org/