如何将堆栈跟踪转换为字符串?

1708

如何最简单地将Throwable.getStackTrace()的结果转换为描述堆栈跟踪的字符串?


8
因为jqno的回答实际上使用了你在问题中指定的Throwable.getStackTrace()方法,而Brian没有使用它。他改用了Throwable.printStackTrace()方法。 - Stijn de Witt
10
几乎每个 Java 项目都应该包含 Apache commons-lang。它包含了许多实现极为常见的开发需求的方便方法。 - Russell Silva
20
这三行代码几乎肯定需要从您调用它们的位置中分离出来。由于您不知道将它们放在哪里,因此它们将与所有其他有用的片段一起放在您的实用工具箱中。瞧!你刚刚重新发明了guava / commons-lang /等等……只是没有那么好。相反,导入一个明智的实用程序库,并节省重新发明轮子。真正的新手标志是认为您可以比库编写者做得更好。 - Andrew Spencer
9
  1. Guava库提供了Throwables.getStackTraceAsString(e)方法。
  2. Apache Commons Lang库提供了ExceptionUtils.getFullStackTrace方法。
  3. 我们可以编写自己的自定义方法。
- user2323036
16
我不明白为什么你们要这样努力地抨击StijndeWitt想通过一些小片段来实现这个目标。编写一个小型实用程序并没有什么危险性(我不认为他是“绝对自大,哦不!他认为自己比Apache优秀!”)。有很多项目,特别是在非Java JVM语言中,真的不想包含Guava或Commons Lang只为了记录堆栈跟踪。我编写Scala和Clojure库,肯定不会为了一个方法而将Apache Commons Lang作为传递性依赖项。 - jm0
显示剩余7条评论
32个回答

1

虽然这是一个老问题,但我想补充一下特殊情况,即您不想打印整个堆栈,通过删除您实际上不感兴趣的某些部分,排除某些类或包。

可以使用SelectivePrintWriter而不是PrintWriter

// This filters out this package and up.
String packageNameToFilter = "org.springframework";

StringWriter sw = new StringWriter();
PrintWriter pw = new SelectivePrintWriter(sw, packageNameToFilter);
e.printStackTrace(pw);
String sStackTrace = sw.toString(); 
System.out.println(sStackTrace);

给定 SelectivePrintWriter 类如下:

public class SelectivePrintWriter extends PrintWriter {
    private boolean on = true;
    private static final String AT = "\tat";
    private String internal;

    public SelectivePrintWriter(Writer out, String packageOrClassName) {
        super(out);
        internal = "\tat " + packageOrClassName;
    }

    public void println(Object obj) {
        if (obj instanceof String) {
            String txt = (String) obj;
            if (!txt.startsWith(AT)) on = true;
            else if (txt.startsWith(internal)) on = false;
            if (on) super.println(txt);
        } else {
            super.println(obj);
        }
    }
}

请注意,这个类可以很容易地适应正则表达式、包含或其他条件进行过滤。同时请注意,它依赖于Throwable的实现细节(不太可能改变,但仍需注意)。

0

使用 Kotlin 快捷方式将堆栈跟踪写入现有的 StringBuilder:

此版本非常快,因为它避免了创建临时字符串并在其中复制的过程。

private fun StringBuilder.appendStackTrace(thr: Throwable) =
    thr.printStackTrace(object : PrintWriter(StringWriter()) {
        override fun println(x: Any?) {
            this@appendStackTrace.append(x)
            this@appendStackTrace.append('\n')
        }
    })

你可以这样调用它:

val s = buildString {
    append("Some text before the stack trace ...\n")
    appendStackTrace(throwable)
    append("Some other stuff")
}

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