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

回答 31 浏览 70.9万 2009-07-19

Throwable.getStackTrace()的结果转换为描述堆栈跟踪的字符串的最简单方法是什么?

ripper234 提问于2009-07-19
因为jqno的答案实际上使用了你在问题中指定的Throwable.getStackTrace()方法,而Brian却没有。他用Throwable.printStackTrace()代替。Stijn de Witt 2012-01-31
几乎每个Java项目都应该包括Apache commons-lang。它包括许多实现极其常见的开发需求的便利方法。Russell Silva 2013-08-15
@StijndeWitt 这三行代码几乎肯定需要从你调用它们的地方进行因式分解。既然你不知道该把它们放在哪里,它们就会和其他有用的片段一起放在你的工具箱里。Bingo!你刚刚重新发明了guava / commons-lang / whatever......只是没有那么好。导入一个合理的实用程序库,而不是重新发明车轮。新手的真正标志是认为你可以做得比库的作者更好Andrew Spencer 2013-10-22
1.Guava有 - Throwables.getStackTraceAsString(e) 2. Apache Commons Lang - ExceptionUtils.getFullStackTrace 3.编写我们自己的自定义方法user2323036 2014-03-10
@AndrewSpencer 我不明白你们为什么这么努力地抨击StijndeWitt想通过一些小片段实现这个目标。写一个小小的实用方法真的没有什么危险(我不认为这是 "SHEER ARROGANCE oh nooooo!!他认为他比Apache好!!")。有大量的项目,特别是在非Java JVM语言中,真的不想包括Guava或Commons Lang只是为了记录堆栈跟踪。我写Scala和Clojure库,当然不会为了一个方法而让Apache Commons Lang成为一个过渡性的依赖。jm0 2016-03-02
31 个回答
#1楼
得票数 2333

使用Throwable.printStackTrace(PrintWriter pw)来发送堆栈跟踪到一个适当的写作者。

import java.io.StringWriter;
import java.io.PrintWriter;

// ...

StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
String sStackTrace = sw.toString(); // stack trace as a string
System.out.println(sStackTrace);
Brian Agnew 提问于2009-07-19
Neuron 修改于2019-02-10
这将修剪堆栈跟踪,与printStackTrace()的方法相同。堆栈中的所有异常都是可见的,但是对于每个异常,堆栈都可能被修剪。任何需要整个跟踪的人都应该考虑这个。Laila Agaev 2013-11-29
事实证明,这正是apache的ExceptionUtils.getStackTrace()方法的作用。实际上,几乎是一模一样的。ticktock 2014-03-04
@BrianAgnew,你不应该关闭StringWriterPrintWriter吗?Muhammad Gelbana 2015-08-02
@MuhammadGelbana - 是的。上述内容是为了方便起见而显示的。我想如果你不这样做,也不会造成什么问题,但我主张以良好的实践为基础。Brian Agnew 2015-08-03
@BrianAgnew,感谢您的回答。这让我很好奇,以下是我的发现。stackoverflow.com/questions/14542535/&hellip.com/share.php?Muhammad Gelbana 2015-08-03
#2楼 已采纳
得票数 1115

可以使用以下方法将Exception 堆栈跟踪转换为String。此类在 Apache commons-lang 中可用,这是具有许多流行开源的最常见的依赖库

org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(Throwable)

amar 提问于2010-01-21
amar 修改于2017-08-17
@Stijn - 为了公平起见(我在下面写了目前投票率最高的答案),值得关注的是,commons-lang的功能更多。Brian Agnew 2012-01-31
@StijndeWitt Commons Lang是很常见的。它已经出现在我工作中的大多数项目/工程中。WhyNotHugo 2012-05-21
@Hugo 谢谢,本来想用StringWriter来避免添加一个新的库--结果发现它已经是我的三个依赖项的一个依赖项。所以对于其他人,请检查你是否已经有了它。Nathanial 2013-04-10
@MartinAsenov - 按照你的逻辑,你永远不会使用这样一个库,对吗?你不会使用它,除非你已经在使用它?Brian Agnew 2013-08-28
顺便说一下,包已经改变了,该类现在在。org.apache.commons.lang3.exception.ExceptionUtils.schmmd 2013-11-13
#3楼
得票数 495

这应该是可行的。

StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
D. Wroblewski 提问于2009-07-19
D. Wroblewski 修改于2012-07-08
简洁的java语境总是令人捧腹大笑。那个printStackTrace应该只返回字符串,把是否打印的决定权留给用户:)dmitry 2015-07-14
printStackTrace在控制台中打印是可以接受的,但至少在默认情况下应该有一个getStackTrace,将其返回为一个字符串Mateus Viccari 2016-10-13
这其中有哪一部分是简洁的?你必须构造两个对象,而这两个对象的存在除了将堆栈跟踪放到一个字符串中之外,没有任何其他目的。ArtOfWarfare 2016-11-14
@dmitry 一个名为printXXX()的方法应该打印出XXX。user207421 2017-08-11
@Greg 其实那根本不是讽刺,只是需要对他说的内容进行简单的解读。Andrew 2017-10-13
#4楼
得票数 261

如果你是为Android开发的,一个更简单的方法是使用这个。

import android.util.Log;

String stackTrace = Log.getStackTraceString(exception); 

其格式与getStacktrace相同,例如。

09-24 16:09:07.042: I/System.out(4844): java.lang.NullPointerException
09-24 16:09:07.042: I/System.out(4844):   at com.temp.ttscancel.MainActivity.onCreate(MainActivity.java:43)
09-24 16:09:07.042: I/System.out(4844):   at android.app.Activity.performCreate(Activity.java:5248)
09-24 16:09:07.043: I/System.out(4844):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
09-24 16:09:07.043: I/System.out(4844):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2162)
09-24 16:09:07.043: I/System.out(4844):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257)
09-24 16:09:07.043: I/System.out(4844):   at android.app.ActivityThread.access$800(ActivityThread.java:139)
09-24 16:09:07.043: I/System.out(4844):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
09-24 16:09:07.043: I/System.out(4844):   at android.os.Handler.dispatchMessage(Handler.java:102)
09-24 16:09:07.043: I/System.out(4844):   at android.os.Looper.loop(Looper.java:136)
09-24 16:09:07.044: I/System.out(4844):   at android.app.ActivityThread.main(ActivityThread.java:5097)
09-24 16:09:07.044: I/System.out(4844):   at java.lang.reflect.Method.invokeNative(Native Method)
09-24 16:09:07.044: I/System.out(4844):   at java.lang.reflect.Method.invoke(Method.java:515)
09-24 16:09:07.044: I/System.out(4844):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
09-24 16:09:07.044: I/System.out(4844):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
Vicky Kapadia 提问于2012-04-30
Pokechu22 修改于2015-11-29
#5楼
得票数 150

Guava's Throwables class

如果你有实际的Throwable实例,Google Guava提供了Throwables.getStackTraceAsString().

举例说明。

String s = Throwables.getStackTraceAsString ( myException ) ;
stumbav 提问于2012-02-15
Neuron 修改于2019-02-10
#6楼
得票数 119

警告:不包括原因(这通常是有用的部分!)。

public String stackTraceToString(Throwable e) {
    StringBuilder sb = new StringBuilder();
    for (StackTraceElement element : e.getStackTrace()) {
        sb.append(element.toString());
        sb.append("\n");
    }
    return sb.toString();
}
jqno 提问于2009-07-19
samthebest 修改于2017-07-31
#7楼
得票数 107

对我来说,最干净、最简单的方法是。

import java.util.Arrays;
Arrays.toString(e.getStackTrace());
Vladas Diržys 提问于2011-12-15
代码是干净的,但输出却不是。你必须在最后做一个.replaceAll(", ", "\n")。然而你失去了printStackTrace建议的缩进。fury 2012-01-09
当你以单行形式记录跟踪时,这一点很有用webjockey 2017-01-24
#8楼
得票数 30
public static String getStackTrace(Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    return sw.toString();
}
Akira Yamamoto 提问于2013-10-03
Akira Yamamoto 修改于2019-01-02
你好,我只想指出,被引用的答案的评论部分指出,StringWriterPrintWriter对象应该是closed....(或者我想只有PrintWriter需要关闭,因为关闭它也应该关闭StringWriter)。Eric 2016-08-16
#9楼
得票数 26

下面的代码允许你以String的格式获得整个stackTrace,而不需要使用像log4J甚至java.util.Logger这样的API:

catch (Exception e) {
    StackTraceElement[] stack = e.getStackTrace();
    String exception = "";
    for (StackTraceElement s : stack) {
        exception = exception + s.toString() + "\n\t\t";
    }
    System.out.println(exception);
    // then you can send the exception string to a external file.
}
dumonderic 提问于2012-10-24
Murilo Vasconcelos 修改于2012-10-24
#10楼
得票数 24

将堆栈跟踪打印成PrintStream,然后将其转换为String

// ...

catch (Exception e)
{
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    e.printStackTrace(new PrintStream(out));
    String str = new String(out.toByteArray());

    System.out.println(str);
}
Baked Inhalf 提问于2018-04-23
Ihor Patsian 修改于2019-09-12
#11楼
得票数 21

这里有一个可以直接复制粘贴到代码中的版本。

import java.io.StringWriter; 
import java.io.PrintWriter;

//Two lines of code to get the exception into a StringWriter
StringWriter sw = new StringWriter();
new Throwable().printStackTrace(new PrintWriter(sw));

//And to actually print it
logger.info("Current stack trace is:\n" + sw.toString());

或者,在一个抓取块中

} catch (Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    logger.info("Current stack trace is:\n" + sw.toString());
}
rouble 提问于2012-06-12
rouble 修改于2016-10-19
#12楼
得票数 20
Arrays.toString(thrown.getStackTrace())

最简单的方法是将结果转换为字符串,我在我的程序中使用这个来打印堆栈跟踪

LOGGER.log(Level.SEVERE, "Query Builder Issue Stack Trace : {0} ,Message : {1} objid {2}", new Object[]{Arrays.toString(e.getStackTrace()), e.getMessage(),objId});
Ramanan Durairaj 提问于2017-12-26
Panu Haaramo 修改于2018-01-26
#13楼
得票数 18

Kotlin >= 1.4

在一个Throwable上使用内置的函数stackTraceToString()

Kotlin < 1.4

扩展Throwable类将给你提供String属性error.stackTraceString

val Throwable.stackTraceString: String
  get() {
    val sw = StringWriter()
    val pw = PrintWriter(sw)
    this.printStackTrace(pw)
    return sw.toString()
  }
vonox7 提问于2017-03-10
vonox7 修改于2021-03-27
从Kotlin 1.4开始,现在有一个内置的API来完成这个kotlinlang.org/api/latest/jvm/stdlib/kotlin/&hellip.com/kotlin.htm。Aguragorn 2021-03-25
#14楼
得票数 14

如果您使用的是Java 8,请尝试这样做

Arrays.stream(e.getStackTrace())
                .map(s->s.toString())
                .collect(Collectors.joining("\n"));

你可以找到由Throwable.java提供的getStackTrace()函数的代码为:

public StackTraceElement[] getStackTrace() {
    return getOurStackTrace().clone();
}

而对于StackTraceElement,它提供了toString(),如下所示:

public String toString() {
    return getClassName() + "." + methodName +
        (isNativeMethod() ? "(Native Method)" :
         (fileName != null && lineNumber >= 0 ?
          "(" + fileName + ":" + lineNumber + ")" :
          (fileName != null ?  "("+fileName+")" : "(Unknown Source)")));
}

因此,只要用"\n"加入StackTraceElement即可。

Pengcheng Zhang 提问于2018-04-10
Brooklyn99 修改于2020-07-28
如果你想限制它,你可以在流上使用limit(5)的方法。Maik 2021-11-04
#15楼
得票数 12

将堆栈跟踪记录打印成字符串

import java.io.PrintWriter;
import java.io.StringWriter;

public class StackTraceUtils {
    public static String stackTraceToString(StackTraceElement[] stackTrace) {
        StringWriter sw = new StringWriter();
        printStackTrace(stackTrace, new PrintWriter(sw));
        return sw.toString();
    }
    public static void printStackTrace(StackTraceElement[] stackTrace, PrintWriter pw) {
        for(StackTraceElement stackTraceEl : stackTrace) {
            pw.println(stackTraceEl);
        }
    }
}

当你想在不创建Throwable实例的情况下打印当前线程的堆栈跟踪时,这很有用--但请注意,创建新的Throwable并从那里获得堆栈跟踪实际上比调用Thread.getStackTrace更快、更便宜。

Jarek Przygódzki 提问于2011-05-11
Jarek Przygódzki 修改于2016-05-15
#16楼
得票数 11
private String getCurrentStackTraceString() {
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    return Arrays.stream(stackTrace).map(StackTraceElement::toString)
            .collect(Collectors.joining("\n"));
}
eddyrokr 提问于2017-09-14
#17楼
得票数 10

代码来自Apache Commons Lang 3.4 (JavaDoc):

public static String getStackTrace(final Throwable throwable) {
    final StringWriter sw = new StringWriter();
    final PrintWriter pw = new PrintWriter(sw, true);
    throwable.printStackTrace(pw);
    return sw.getBuffer().toString();
}

与其他答案的不同之处在于,它在PrintWriter上使用了autoFlush

IvanRF 提问于2015-07-07
IvanRF 修改于2016-10-06
#18楼
得票数 9

第一组评论中的巧妙狙击非常有趣,但这真的取决于你想做什么。如果你还没有正确的库,那么3行代码(如D.Wroblewski的答案)就很完美了。 相反,如果你已经有了apache.commons库(大多数大型项目都会有),那么Amar的答案就更短了。 好吧,你可能需要10分钟来获取库并正确安装它(如果你知道自己在做什么,那么不到一分钟)。Jarek Przygódzki有一个有趣的警告--"如果你不需要嵌套异常"。

但是如果我确实需要完整的堆栈跟踪,嵌套和所有?在这种情况下,秘诀是使用 apache.common 的 getFullStackTrace(参见 http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/ lang/exception/ExceptionUtils.html#getFullStackTrace%28java.lang.Throwable%29)

它拯救了我的培根。谢谢你,阿玛尔,谢谢你的提示!

Tihamer 提问于2014-04-15
#19楼
得票数 8

如果没有java.io.*,可以这样做。

String trace = e.toString() + "\n";                     

for (StackTraceElement e1 : e.getStackTrace()) {
    trace += "\t at " + e1.toString() + "\n";
}   

然后trace 变量保存您的堆栈跟踪。输出也包含初始原因,输出与printStackTrace()相同

例如,printStackTrace()产生的结果是:

java.io.FileNotFoundException: / (Is a directory)
    at java.io.FileOutputStream.open0(Native Method)
    at java.io.FileOutputStream.open(FileOutputStream.java:270)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:101)
    at Test.main(Test.java:9)

trace 字符串持有,当打印到stdout

java.io.FileNotFoundException: / (Is a directory)
     at java.io.FileOutputStream.open0(Native Method)
     at java.io.FileOutputStream.open(FileOutputStream.java:270)
     at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
     at java.io.FileOutputStream.<init>(FileOutputStream.java:101)
     at Test.main(Test.java:9)
Gala 提问于2016-06-07
Gala 修改于2016-06-07
#20楼
得票数 7

使用Java 8 流媒体API,您可以做这样的事情。

Stream
    .of(throwable.getStackTrace())
    .map(StackTraceElement::toString)
    .collect(Collectors.joining("\n"));

它将接收堆栈跟踪元素的数组,将它们转换为字符串,并连接成多行字符串。

ivanjermakov 提问于2019-09-29
这个解决方案正在删除信息,并忽略了所有的父级跟踪。judovana 2019-11-07
#21楼
得票数 5

对笪瞵岔语的回答,也将包括例外情况的原因。

private String extrapolateStackTrace(Exception ex) {
    Throwable e = ex;
    String trace = e.toString() + "\n";
    for (StackTraceElement e1 : e.getStackTrace()) {
        trace += "\t at " + e1.toString() + "\n";
    }
    while (e.getCause() != null) {
        e = e.getCause();
        trace += "Cause by: " + e.toString() + "\n";
        for (StackTraceElement e1 : e.getStackTrace()) {
            trace += "\t at " + e1.toString() + "\n";
        }
    }
    return trace;
}
ido flax 提问于2016-07-15
#22楼
得票数 5

Scala版本

def stackTraceToString(e: Exception): String = {
  import java.io.PrintWriter
  val sw = new StringWriter()
  e.printStackTrace(new PrintWriter(sw))
  sw.toString
}
samthebest 提问于2019-03-05
#23楼
得票数 4

如果您不想使用外部库,并且您没有开发for Android,您可以像这样创建一个'扩展'方法

public static String getStackTraceString(Throwable e) {
    return getStackTraceString(e, "");
}

private static String getStackTraceString(Throwable e, String indent) {
    StringBuilder sb = new StringBuilder();
    sb.append(e.toString());
    sb.append("\n");

    StackTraceElement[] stack = e.getStackTrace();
    if (stack != null) {
        for (StackTraceElement stackTraceElement : stack) {
            sb.append(indent);
            sb.append("\tat ");
            sb.append(stackTraceElement.toString());
            sb.append("\n");
        }
    }

    Throwable[] suppressedExceptions = e.getSuppressed();
    // Print suppressed exceptions indented one level deeper.
    if (suppressedExceptions != null) {
        for (Throwable throwable : suppressedExceptions) {
            sb.append(indent);
            sb.append("\tSuppressed: ");
            sb.append(getStackTraceString(throwable, indent + "\t"));
        }
    }

    Throwable cause = e.getCause();
    if (cause != null) {
        sb.append(indent);
        sb.append("Caused by: ");
        sb.append(getStackTraceString(cause, indent));
    }

    return sb.toString();
}
Kapé 提问于2014-09-13
Community 修改于2017-05-23
#24楼
得票数 4

解决方案是将数组的 stackTrace 转换为字符串数据类型。请看下面的例子。

import java.util.Arrays;

try{

}catch(Exception ex){
    String stack = Arrays.toString(ex.getStackTrace());
    System.out.println("stack "+ stack);
}
Jorge Santos 提问于2018-03-30
#25楼
得票数 3

我的oneliner,将堆栈跟踪转换为所附的多行字符串。

Stream.of(e.getStackTrace()).map((a) -> a.toString()).collect(Collectors.joining("\n", "[", "]"))

很容易 "按原样 "传递给记录器。

Andrey Lebedenko 提问于2018-03-17
你得到的东西与printStackTrace()不同,在这里你将失去:1)被抛出的异常;2)原因和它们的堆栈跟踪。valijon 2018-12-11
这种差异是可以预料的,因为转换printStackTrace()从来都不是问题的一部分。Andrey Lebedenko 2018-12-11
#26楼
得票数 3

少量的选择

  1. StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); String exceptionAsString = sw.toString();

  2. 使用Google Guava lib String stackTrace = Throwables.getStackTraceAsString ( myException ) ;

  3. org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(Throwable)

Eric 提问于2018-10-30
#27楼
得票数 3
 import java.io.PrintWriter;
import java.io.StringWriter;

public class PrintStackTrace {

    public static void main(String[] args) {

        try {
            int division = 0 / 0;
        } catch (ArithmeticException e) {
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw));
            String exceptionAsString = sw.toString();
            System.out.println(exceptionAsString);
        }
    }
}

当你运行该程序时,输出结果将是类似的东西。

java.lang.ArithmeticException: / by zero
at PrintStackTrace.main(PrintStackTrace.java:9)
Prakhar Nigam 提问于2018-11-17
#28楼
得票数 3

我想知道为什么没有人提到ExceptionUtils.getStackFrames(exception)

对我来说,这是最方便的方式,可以将堆栈跟踪及其所有原因转储到最后。

String.join("\n", ExceptionUtils.getStackFrames(exception));
Andrey Sarul 提问于2020-04-13
Andrey Sarul 修改于2020-05-09
和什么是ExceptionUtils?Stealth Rabbi 2020-08-11
这是一个通用的Lang利用类。Andrey Sarul 2020-08-13
#29楼
得票数 2

老问题了,但我只想补充一个特殊的情况,即你不想打印所有的堆栈,通过删除一些你实际上不感兴趣的部分,排除某些类或包。

使用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);
        }
    }
}

请注意,此类可以很容易地适应正则表达式、contains 或其他条件进行过滤。另请注意,这取决于Throwable 实现细节(不太可能改变,但仍然如此)。

MarcG 提问于2017-10-16
gil.fernandes 修改于2017-11-03
#30楼
得票数 2

警告。这可能有点偏离主题,但是哦,好吧...;)

我不知道最初的发帖者reason是什么原因想把堆栈跟踪变成字符串。当堆栈跟踪应该在SLF4J/Logback LOG中结束,但没有抛出或应该抛出异常时,我是这样做的:

public void remove(List<String> ids) {
    if(ids == null || ids.isEmpty()) {
        LOG.warn(
            "An empty list (or null) was passed to {}.remove(List). " +
            "Clearly, this call is unneccessary, the caller should " + 
            "avoid making it. A stacktrace follows.", 
            getClass().getName(),
            new Throwable ("Stacktrace")
        );

        return;
    }

    // actual work, remove stuff
}

我喜欢它,因为它不需要外部库(除了你的日志后端,当然,大部分时间都会在这里)。

Alexander Wessel 提问于2017-12-06
#31楼
得票数 2

我不久前写了一些这方面的方法,所以我想为什么不把我的两分钱扔在这里呢。

/** @param stackTraceElements The elements to convert
 * @return The resulting string */
public static final String stackTraceElementsToStr(StackTraceElement[] stackTraceElements) {
    return stackTraceElementsToStr(stackTraceElements, "\n");
}

/** @param stackTraceElements The elements to convert
 * @param lineSeparator The line separator to use
 * @return The resulting string */
public static final String stackTraceElementsToStr(StackTraceElement[] stackTraceElements, String lineSeparator) {
    return stackTraceElementsToStr(stackTraceElements, lineSeparator, "");
}

/** @param stackTraceElements The elements to convert
 * @param lineSeparator The line separator to use
 * @param padding The string to be used at the start of each line
 * @return The resulting string */
public static final String stackTraceElementsToStr(StackTraceElement[] stackTraceElements, String lineSeparator, String padding) {
    String str = "";
    if(stackTraceElements != null) {
        for(StackTraceElement stackTrace : stackTraceElements) {
            str += padding + (!stackTrace.toString().startsWith("Caused By") ? "\tat " : "") + stackTrace.toString() + lineSeparator;
        }
    }
    return str;
}

/** @param stackTraceElements The elements to convert
 * @return The resulting string */
public static final String stackTraceCausedByElementsOnlyToStr(StackTraceElement[] stackTraceElements) {
    return stackTraceCausedByElementsOnlyToStr(stackTraceElements, "\n");
}

/** @param stackTraceElements The elements to convert
 * @param lineSeparator The line separator to use
 * @return The resulting string */
public static final String stackTraceCausedByElementsOnlyToStr(StackTraceElement[] stackTraceElements, String lineSeparator) {
    return stackTraceCausedByElementsOnlyToStr(stackTraceElements, lineSeparator, "");
}

/** @param stackTraceElements The elements to convert
 * @param lineSeparator The line separator to use
 * @param padding The string to be used at the start of each line
 * @return The resulting string */
public static final String stackTraceCausedByElementsOnlyToStr(StackTraceElement[] stackTraceElements, String lineSeparator, String padding) {
    String str = "";
    if(stackTraceElements != null) {
        for(StackTraceElement stackTrace : stackTraceElements) {
            str += (!stackTrace.toString().startsWith("Caused By") ? "" : padding + stackTrace.toString() + lineSeparator);
        }
    }
    return str;
}

/** @param e The {@link Throwable} to convert
 * @return The resulting String */
public static final String throwableToStrNoStackTraces(Throwable e) {
    return throwableToStrNoStackTraces(e, "\n");
}

/** @param e The {@link Throwable} to convert
 * @param lineSeparator The line separator to use
 * @return The resulting String */
public static final String throwableToStrNoStackTraces(Throwable e, String lineSeparator) {
    return throwableToStrNoStackTraces(e, lineSeparator, "");
}

/** @param e The {@link Throwable} to convert
 * @param lineSeparator The line separator to use
 * @param padding The string to be used at the start of each line
 * @return The resulting String */
public static final String throwableToStrNoStackTraces(Throwable e, String lineSeparator, String padding) {
    if(e == null) {
        return "null";
    }
    String str = e.getClass().getName() + ": ";
    if((e.getMessage() != null) && !e.getMessage().isEmpty()) {
        str += e.getMessage() + lineSeparator;
    } else {
        str += lineSeparator;
    }
    str += padding + stackTraceCausedByElementsOnlyToStr(e.getStackTrace(), lineSeparator, padding);
    for(Throwable suppressed : e.getSuppressed()) {
        str += padding + throwableToStrNoStackTraces(suppressed, lineSeparator, padding + "\t");
    }
    Throwable cause = e.getCause();
    while(cause != null) {
        str += padding + "Caused by:" + lineSeparator + throwableToStrNoStackTraces(e.getCause(), lineSeparator, padding);
        cause = cause.getCause();
    }
    return str;
}

/** @param e The {@link Throwable} to convert
 * @return The resulting String */
public static final String throwableToStr(Throwable e) {
    return throwableToStr(e, "\n");
}

/** @param e The {@link Throwable} to convert
 * @param lineSeparator The line separator to use
 * @return The resulting String */
public static final String throwableToStr(Throwable e, String lineSeparator) {
    return throwableToStr(e, lineSeparator, "");
}

/** @param e The {@link Throwable} to convert
 * @param lineSeparator The line separator to use
 * @param padding The string to be used at the start of each line
 * @return The resulting String */
public static final String throwableToStr(Throwable e, String lineSeparator, String padding) {
    if(e == null) {
        return "null";
    }
    String str = padding + e.getClass().getName() + ": ";
    if((e.getMessage() != null) && !e.getMessage().isEmpty()) {
        str += e.getMessage() + lineSeparator;
    } else {
        str += lineSeparator;
    }
    str += padding + stackTraceElementsToStr(e.getStackTrace(), lineSeparator, padding);
    for(Throwable suppressed : e.getSuppressed()) {
        str += padding + "Suppressed: " + throwableToStr(suppressed, lineSeparator, padding + "\t");
    }
    Throwable cause = e.getCause();
    while(cause != null) {
        str += padding + "Caused by:" + lineSeparator + throwableToStr(e.getCause(), lineSeparator, padding);
        cause = cause.getCause();
    }
    return str;
}

举例说明。

try(InputStream in = new FileInputStream(file)) {
    ...
} catch(IOException e) {
    String exceptionToString = throwableToStr(e);
    someLoggingUtility.println(exceptionToString);
    ...
}

印刷品:

java.io.FileNotFoundException: C:\test.txt (The system cannot find the file specified)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(Unknown Source)
    at java.io.FileInputStream.<init>(Unknown Source)
    at com.gmail.br45entei.Example.main(Example.java:32)
Brian_Entei 提问于2019-01-13