如何将 java 日志记录控制台输出从 std err 更改为 std out?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/194165/
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
How do I change java logging console output from std err to std out?
提问by Obediah Stane
I'm using the standard ConsoleHandler
from java.util.logging
and by default the console output is directed to the error stream (i.e. System.err
).
我正在使用标准ConsoleHandler
fromjava.util.logging
并且默认情况下控制台输出被定向到错误流(即System.err
)。
How do I change the console output to the output stream (i.e. System.out
)?
如何将控制台输出更改为输出流(即System.out
)?
回答by Jon Skeet
Have a look at the docs and source for ConsoleHandler- I'm sure you could easily write a version which just uses System.err instead of System.out. (It's a shame that ConsoleHandler doesn't allow this to be configured, to be honest.)
查看ConsoleHandler的文档和源代码- 我相信您可以轻松编写一个仅使用 System.err 而不是 System.out 的版本。(说实话,ConsoleHandler 不允许配置它,这是一种耻辱。)
Then it's just a case of configuring the logging system to use your new StdoutHandler (or whatever you call it) in the normal way.
然后,这只是将日志系统配置为以正常方式使用新的 StdoutHandler(或任何您称之为)的情况。
回答by Uri
If you use Java logging, you can change the default handler:
如果您使用 Java 日志记录,则可以更改默认处理程序:
For example, for files: Handler fh = new FileHandler(FILENAME); Logger.getLogger(LOGGER_NAME).addHandler(fh);
例如,对于文件:Handler fh = new FileHandler(FILENAME); Logger.getLogger(LOGGER_NAME).addHandler(fh);
If you want to output to a stream you can use StreamHandler, I think you can configure it with any output stream that you woud like, including the system stream.
如果你想输出到流,你可以使用StreamHandler,我想你可以用你喜欢的任何输出流配置它,包括系统流。
回答by Obediah Stane
I figured out one way. First remove the default console handler:
我想出了一种方法。首先删除默认的控制台处理程序:
setUseParentHandlers(false);
setUseParentHandlers(false);
Then subclass ConsoleHandler and in the constructor:
然后子类 ConsoleHandler 并在构造函数中:
setOutputStream(System.out);
setOutputStream(System.out);
回答by Obediah Stane
If you set setUseParentHandlers(false); only THAT class has it set. Other classes in the app will still pass it thru to stderr.
如果你设置了 setUseParentHandlers(false); 只有那个班级设置了它。应用程序中的其他类仍会将其传递给 stderr。
回答by Hema
Simply extend StreamHandler & in the constructor call Super(System.out,). This will avoid closing System.err - Thanks
只需在构造函数调用 Super(System.out,) 中扩展 StreamHandler &。这将避免关闭 System.err - 谢谢
回答by Jeremiah Jahn
Handler consoleHandler = new Handler(){
@Override
public void publish(LogRecord record)
{
if (getFormatter() == null)
{
setFormatter(new SimpleFormatter());
}
try {
String message = getFormatter().format(record);
if (record.getLevel().intValue() >= Level.WARNING.intValue())
{
System.err.write(message.getBytes());
}
else
{
System.out.write(message.getBytes());
}
} catch (Exception exception) {
reportError(null, exception, ErrorManager.FORMAT_FAILURE);
}
}
@Override
public void close() throws SecurityException {}
@Override
public void flush(){}
};
回答by Frank Vlach
I've arrived at
我到了
SimpleFormatter fmt = new SimpleFormatter();
StreamHandler sh = new StreamHandler(System.out, fmt);
logger.addHandler(sh);
回答by volley
Hmm I just got bit in the foot a few times, trying to accomplish this feat. Before googling my way here I managed to conjure the following hack. Ugly, but it seems to get the job done.
嗯,我只是被咬了几次脚,试图完成这个壮举。在谷歌搜索我的方式之前,我设法召唤了以下黑客。丑陋,但它似乎完成了工作。
public class StdoutConsoleHandler extends ConsoleHandler {
protected void setOutputStream(OutputStream out) throws SecurityException {
super.setOutputStream(System.out); // kitten killed here :-(
}
}
Watch out: Calling setOutputStream() from the constructor is tempting, but it does (as Jon Skeet already pointed out) close System.err. Mad skills!
注意:从构造函数调用 setOutputStream() 很诱人,但它确实(正如 Jon Skeet 已经指出的那样)关闭 System.err。疯狂的技能!
回答by Kai
If there is still someone out there looking for a solution to this problem. Here's what I came up with finally: I just subclassed StreamHandler and added an additional parameter MaxLevel, which is checked at the beginning of publish(). If the level of the logging event is larger than MaxLevel, publish won't be executed any further. Here are the details:
如果仍然有人在那里寻找解决此问题的方法。这是我最后想到的:我只是继承了 StreamHandler 并添加了一个额外的参数 MaxLevel,它在 publish() 的开头被检查。如果日志事件的级别大于 MaxLevel,则发布将不再执行。以下是详细信息:
MaxlevelStreamHandler.javaMain Class below.
MaxlevelStreamHandler.java下面的主类。
package helper;
/**
* The only difference to the standard StreamHandler is
* that a MAXLEVEL can be defined (which then is not published)
*
* @author Kai Goergen
*/
import java.io.PrintStream;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.StreamHandler;
public class MaxlevelStreamHandler extends StreamHandler {
private Level maxlevel = Level.SEVERE; // by default, put out everything
/**
* The only method we really change to check whether the message
* is smaller than maxlevel.
* We also flush here to make sure that the message is shown immediately.
*/
@Override
public synchronized void publish(LogRecord record) {
if (record.getLevel().intValue() > this.maxlevel.intValue()) {
// do nothing if the level is above maxlevel
} else {
// if we arrived here, do what we always do
super.publish(record);
super.flush();
}
}
/**
* getter for maxlevel
* @return
*/
public Level getMaxlevel() {
return maxlevel;
}
/**
* Setter for maxlevel.
* If a logging event is larger than this level, it won't be displayed
* @param maxlevel
*/
public void setMaxlevel(Level maxlevel) {
this.maxlevel = maxlevel;
}
/** Constructor forwarding */
public MaxlevelStreamHandler(PrintStream out, Formatter formatter) {
super(out, formatter);
}
/** Constructor forwarding */
public MaxlevelStreamHandler() {
super();
}
}
Main Class
主类
To now show some events in stdout and some in stderr, simply setup two StreamLoggers, one for critical events and one for all others, and disable the standard console logger:
现在要在 stdout 中显示一些事件,在 stderr 中显示一些事件,只需设置两个 StreamLogger,一个用于关键事件,一个用于所有其他事件,并禁用标准控制台记录器:
// setup all logs that are smaller than WARNINGS to stdout
MaxlevelStreamHandler outSh = new MaxlevelStreamHandler(System.out, formatter);
outSh.setLevel(Level.ALL);
outSh.setMaxlevel(Level.INFO);
logger.addHandler(outSh);
// setup all warnings to stdout & warnings and higher to stderr
StreamHandler errSh = new StreamHandler(System.err, formatter);
errSh.setLevel(Level.WARNING);
logger.addHandler(errSh);
// remove default console logger
logger.setUseParentHandlers(false);
logger.info("info");
logger.warning("warning");
logger.severe("severe");
Hope this helps!
希望这可以帮助!
Update: I added super.flush() right after super.publish() to make sure that the message is shown immediately. Before, I had problems that the log-messages were always shown at the end. It's now part of the code above.
更新:我在 super.publish() 之后添加了 super.flush() 以确保立即显示消息。之前,我遇到了日志消息总是显示在最后的问题。它现在是上面代码的一部分。
回答by ocarlsen
I had a similar problem. I wanted to log INFO and below to System.out
, and WARNING and above to System.err
. Here is the solution I implemented:
我有一个类似的问题。我想将 INFO 及以下记录到System.out
,并将 WARNING 及以上记录到System.err
. 这是我实施的解决方案:
public class DualConsoleHandler extends StreamHandler {
private final ConsoleHandler stderrHandler = new ConsoleHandler();
public DualConsoleHandler() {
super(System.out, new SimpleFormatter());
}
@Override
public void publish(LogRecord record) {
if (record.getLevel().intValue() <= Level.INFO.intValue()) {
super.publish(record);
super.flush();
} else {
stderrHandler.publish(record);
stderrHandler.flush();
}
}
}
Of course, you could make it more flexible by factoring out the hard-coded reference to Level.INFO
, for example. But this worked well for me to get some basic dual-stream logging. (BTW, the tips about not subclassing ConsoleHandler to avoid closing the System.err
were very useful.)
当然,例如,您可以通过分解对 的硬编码引用来使其更加灵活Level.INFO
。但这对我来说很有效,可以得到一些基本的双流日志记录。(顺便说一句,关于不要子类化 ConsoleHandler 以避免关闭的提示System.err
非常有用。)