将printStackTrace转换为java.util.logging.Logger

36
如何使用java.util.Logger打印整个堆栈跟踪?(不使用Netbeans)
该问题最初应该指定在Java SE内完成。我犯了一个错误,没有说明这个要求。
-do-compile:
    [mkdir] Created dir: /home/thufir/NetBeansProjects/rainmaker/build/empty
    [mkdir] Created dir: /home/thufir/NetBeansProjects/rainmaker/build/generated-sources/ap-source-output
    [javac] Compiling 13 source files to /home/thufir/NetBeansProjects/rainmaker/build/classes
    [javac] /home/thufir/NetBeansProjects/rainmaker/src/model/TelnetEventProcessor.java:44: error: 'void' type not allowed here
    [javac]                 log.severe(npe.printStackTrace(System.out));
    [javac]                                               ^
    [javac] 1 error

BUILD FAILED

出现错误的代码:

package model;

import java.util.Observable;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TelnetEventProcessor extends Observable {

    private static Logger log = Logger.getLogger(TelnetEventProcessor.class.getName());
    private String string = null;

    public TelnetEventProcessor() {
    }

    private void stripAnsiColors() {
        Pattern regex = Pattern.compile("\\e\\[[0-9;]*m");
        Matcher regexMatcher = regex.matcher(string);
        string = regexMatcher.replaceAll(""); // *3 ??
    }

    public void parse(String string) {
        this.string = string;
        ifs();
    }

    //       [\w]+(?=\.) 
    private void ifs() {
        log.fine("checking..");
        if (string.contains("confusing the hell out of")) {
            Pattern pattern = Pattern.compile("[\\w]+(?=\\.)");  //(\w+)\.
            Matcher matcher = pattern.matcher(string);
            String enemy = null;
            GameData data = null;
            while (matcher.find()) {
                enemy = matcher.group();
            }
            try {
                data = new GameData.Builder().enemy(enemy).build();
                log.fine("new data object\t\t" + data.getEnemy());
                setChanged();
                notifyObservers(data);
            } catch (NullPointerException npe) {
                log.severe(npe.printStackTrace(System.out));
            }

        } else if (string.contains("Enter 3-letter city code:")) {
            log.fine("found enter city code");
        } else {
        }
    }
}

参见:

https://dev59.com/jWw05IYBdhLWcg3wqzms#7100975

8个回答

52

severe 方法仅用于记录严重的消息,没有相关的可抛出信息。如果您需要记录可抛出信息,则应使用 log 方法:

try {
     data = new GameData.Builder().enemy(enemy).build();
     log.fine("new data object\t\t" + data.getEnemy());
     setChanged();
     notifyObservers(data);
} catch (NullPointerException npe) {
     log.log(Level.SEVERE, npe.getMessage(), npe);
}

2
这个答案唯一的问题就是过于冗长了——但这就是Java的特点! - Thufir
这是我第一次看到有人捕获 NP 异常! - hzitoun

12

为什么不把异常放在日志记录器中?

你可以使用这个方法:

logger.log(Level level, String msg, Throwable thrown) 

我认为这是实现所需结果的最简单方法。当然,还需要尝试一下。 - Thufir

9

也许是重复的问题?Java - 需要一个可以记录堆栈跟踪的日志记录包

下面是来自给定网址的解释

Using log4j this is done with:

logger.error("An error occurred", exception);

The first argument is a message to be displayed, the second is the exception (throwable) whose stacktrace is logged.

Another option is commons-logging, where it's the same:

log.error("Message", exception);

With java.util.logging this can be done via:

logger.log(Level.SEVERE, "Message", exception);

这正是我在寻找的。谢谢。 - Shashank

7

您不需要显式打印堆栈跟踪; Throwable对象有与它们相关的堆栈跟踪,并且您可以将Throwable对象传递给日志记录方法:

log(Level level, String msg, Throwable thrown)

4
你可以使用Apache ExceptionUtils。在你的情况下,
try {
     data = new GameData.Builder().enemy(enemy).build();
     log.fine("new data object\t\t" + data.getEnemy());
     setChanged();
     notifyObservers(data);
 } catch (NullPointerException npe) {
     logger.info(**ExceptionUtils.getFullStackTrace(npe)**);
 }

1
你的解决方案帮了我很大忙。另一个解决方法是:logger.severe(Arrays.toString(e.getStackTrace())); - user3181500

3

您应该将System.err重定向到日志记录器,这个过程不太简单,但您可以使用以下代码:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class LogOutputStream extends ByteArrayOutputStream {//java.io.OutputStream {

    private String  lineSeparator;
    private Logger  logger;
    private Level   level;

    public LogOutputStream(Logger logger, Level level) {
        super();
        this.logger = logger;
        this.level = level;
        this.lineSeparator = System.getProperty("line.separator");
    }

    @Override
    public void flush() throws IOException {

        String record;
        synchronized (this) {
            super.flush();
            record = this.toString();
            super.reset();

            if ((record.length() == 0) || record.equals(this.lineSeparator)) {
                // avoid empty records 
                return;
            }

            this.logger.logp(this.level, "", "", record);
        }
    }
}

下面是用于设置此功能的代码(应该在首次创建记录器时调用):

Logger logger = Logger.getLogger("Exception");
LogOutputStream los = new LogOutputStream(logger, Level.SEVERE);
System.setErr(new PrintStream(los, true));

这将把System.err流重定向到记录器。


1
异常是由于printstacktrace方法是void,意味着它不返回任何东西。你正在尝试执行:

log.severe(npe.printStackTrace(System.out));

我猜测 severe 方法需要一个 String 而不是 void

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接