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

rip*_*234 1435 java tostring stack-trace

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

Bri*_*new 2146

使用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);
Run Code Online (Sandbox Code Playgroud)

  • 如果您不喜欢将外部库包含在这样小而简单的内容中,请使用此答案. (487认同)
  • @BrianAgnew,谢谢你的回复.它让我很好奇,这就是我发现的:http://stackoverflow.com/questions/14542535/will-not-closing-a-stringwriter-cause-a-leak (12认同)
  • 这确实修剪了堆栈跟踪,就像printStackTrace()一样.堆栈中的所有异常都是可见的,但是对于每个异常,可以修剪堆栈.任何需要整个跟踪的人都应该考虑这一点 (8认同)
  • @BrianAgnew,你不应该关闭`StringWriter`和`PrintWriter`吗? (6认同)
  • 事实证明,这正是apache的ExceptionUtils.getStackTrace()方法所做的.实际上几乎到了这封信. (5认同)
  • @MuhammadGelbana - 是的.以上显示是为了方便.我怀疑如果你不这样做不会引起问题,但我会以良好做法为由提倡 (5认同)
  • @MuhammadGelbana实际上没有必要在这种情况下关闭编写器**因为关闭`PrintWriter`只是关闭委托对象.关闭`StringWriter`什么都不做.此外,调用`PrintWriter.flush()`是没有用的,因为当你使用缓冲流时这是适用的 (4认同)
  • 我认为应该在`sw.toString()`之前调用`pw.flush()`.默认情况下,"PrintWriter"未自动设置为刷新. (2认同)

ama*_*mar 996

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

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

  • @Stijn - 公平(我在下面写了当前最高的投票答案)值得看看commons-lang以获得更多功能 (86认同)
  • @StijndeWitt Commons Lang非常普遍.它已经出现在我工作的大部分项目/项目中. (53认同)
  • @MartinAsenov - 按照你的逻辑你永远不会使用这样的库,不是吗?除非你已经在使用它,否则你不会使用它? (32认同)
  • @Hugo谢谢,打算使用StringWriter来避免添加一个新库 - 结果证明它已经是我的3个依赖项的依赖项.所以对其他人来说,检查一下你是否已经拥有它. (16认同)
  • Fyi,包已更改,类现在位于:`org.apache.commons.lang3.exception.ExceptionUtils`. (13认同)
  • 一行需要一个外部库,但我可以打赌我的屁股你也需要StringUtils所以它实际上是一个非参数. (7认同)
  • 自己编写它需要花费超过几行.如果要使用此功能两次,那么您将创建一个实用程序类,添加更多行对象.当然,你正在编写单元测试以保证其行为,对吧? (6认同)
  • 您不建议为此类简单功能包括一个外部库,除非您已经在使用该特定外部库。这是许多开发人员的常见不良做法 (2认同)
  • 包括一个可保存3行代码的庞大库吗?失败。 (2认同)

D. *_*ski 448

这应该工作:

StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
Run Code Online (Sandbox Code Playgroud)

  • 简洁的java上下文总是很有趣.那个`printStackTrace`应该只返回字符串,决定是否打印到用户:) (64认同)
  • 在控制台中打印printStackTrace是可以接受的,但至少应该将一个getStackTrace作为String返回 (30认同)
  • @ArtOfWarfare他显然是在讽刺. (8认同)
  • @dmitry一个名为`printXXX()`的方法应该打印XXX. (5认同)
  • 这部分内容简洁明了?除了将堆栈跟踪放入字符串之外,您必须构造2个除了目的之外的对象. (4认同)
  • @Greg实际上,这甚至没有讽刺意味,只需要简单地阅读他的话即可。 (2认同)
  • @Smit-Tay 好吧,在专业环境中,我几乎不需要在任何地方直接打印异常 - 它通常会传递到日志记录库,并且日志记录配置负责处理有关详细程度的所有详细信息异常最终出现在哪个日志文件中,以及它如何在那里格式化。 (2认同)

Vic*_*dia 214

如果您正在为Android开发,更简单的方法是使用它:

import android.util.Log;

String stackTrace = Log.getStackTraceString(exception); 
Run Code Online (Sandbox Code Playgroud)

格式与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)
Run Code Online (Sandbox Code Playgroud)

  • 谢谢.在这种情况下,日期和标记不会像printStackTrace()中那样写入每一行. (2认同)
  • 在Android日志中仅打印它的最简单方法是:Log.e(“ TAG”,“我的消息”,new Throwable());` (2认同)

小智 124

番石榴的Throwables班级

如果你有实际的Throwable实例,谷歌番石榴提供Throwables.getStackTraceAsString().

例:

String s = Throwables.getStackTraceAsString ( myException ) ;
Run Code Online (Sandbox Code Playgroud)


jqn*_*qno 111

警告:不包括原因(通常是有用的位!)

public String stackTraceToString(Throwable e) {
    StringBuilder sb = new StringBuilder();
    for (StackTraceElement element : e.getStackTrace()) {
        sb.append(element.toString());
        sb.append("\n");
    }
    return sb.toString();
}
Run Code Online (Sandbox Code Playgroud)

  • 无论你做什么,都不要修剪痕迹.很多次,我在GlassFish日志中查看了堆栈跟踪,其中包含了有用的部分. (6认同)
  • 不确定,但我认为这不会打印根本原因异常的堆栈跟踪. (2认同)

Vla*_*žys 88

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

import java.util.Arrays;
Arrays.toString(e.getStackTrace());
Run Code Online (Sandbox Code Playgroud)

  • 代码很干净,但输出却没有.你最后必须做一个.replaceAll(",","\n").但是你丢失了printStackTrace建议的缩进. (35认同)
  • 当您在一行中记录跟踪时,这非常有用 (4认同)

Aki*_*oto 28

public static String getStackTrace(Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    return sw.toString();
}
Run Code Online (Sandbox Code Playgroud)

  • 灵感你的意思是复制?你只把它放在一个方法中...在这里阅读答案就像看"土拨鼠日" (7认同)

小智 26

以下代码允许您String使用格式获取整个stackTrace ,而无需使用log4J等甚至是API java.util.Logger:

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.
}
Run Code Online (Sandbox Code Playgroud)


rou*_*ble 19

这是一个可以直接复制到代码中的版本:

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());
Run Code Online (Sandbox Code Playgroud)

或者,在一个捕获块中

} catch (Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    logger.info("Current stack trace is:\n" + sw.toString());
}
Run Code Online (Sandbox Code Playgroud)


Ram*_*raj 14

Arrays.toString(thrown.getStackTrace())
Run Code Online (Sandbox Code Playgroud)

是将结果转换为String的最简单方法我在程序中使用它来打印堆栈跟踪

LOGGER.log(Level.SEVERE, "Query Builder Issue Stack Trace : {0} ,Message : {1} objid {2}", new Object[]{Arrays.toString(e.getStackTrace()), e.getMessage(),objId});
Run Code Online (Sandbox Code Playgroud)


Bak*_*alf 13

将stacktrace打印到PrintStream,然后将其转换为String

// ...

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

    System.out.println(str);
}
Run Code Online (Sandbox Code Playgroud)


Jar*_*zki 11

将堆栈跟踪打印到字符串

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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


von*_*ox7 10

科特林

扩展Throwable类将为您提供String属性error.stackTraceString:

val Throwable.stackTraceString: String
  get() {
    val sw = StringWriter()
    val pw = PrintWriter(sw)
    this.printStackTrace(pw)
    return sw.toString()
  }
Run Code Online (Sandbox Code Playgroud)


edd*_*okr 10

private String getCurrentStackTraceString() {
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    return Arrays.stream(stackTrace).map(StackTraceElement::toString)
            .collect(Collectors.joining("\n"));
}
Run Code Online (Sandbox Code Playgroud)


Tih*_*mer 9

第一组评论中的聪明狙击是非常有趣的,但这实际上取决于你想要做什么.如果你还没有正确的库,那么3行代码(如在D. Wroblewski的答案中)是完美的.OTOH,如果你已经有了apache.commons库(就像大多数大型项目那样),那么Amar的答案就更短了.好的,你可能需要十分钟才能获得库并正确安装(如果你知道你在做什么的话,不到一个).但是时间在流逝,所以你可能没有时间.JarekPrzygó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)

它救了我的培根.谢谢,阿玛,提示!


Iva*_*nRF 9

代码的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();
}
Run Code Online (Sandbox Code Playgroud)

与其他答案的不同之处在于它使用 autoFlushPrintWriter.


iva*_*kov 7

使用 Java 8 Stream API,您可以执行以下操作:

Stream
    .of(throwable.getStackTrace())
    .map(StackTraceElement::toString)
    .collect(Collectors.joining("\n"));
Run Code Online (Sandbox Code Playgroud)

它将获取堆栈跟踪元素数组,将它们转换为字符串并加入多行字符串。

  • 此解决方案正在删除消息并忽略所有父跟踪 (4认同)

Gal*_*ala 6

没有java.io.*它可以这样做.

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

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

然后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)
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)


ido*_*lax 5

对 Gala 答案的扩展,其中还将包括异常的原因:

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;
}
Run Code Online (Sandbox Code Playgroud)


小智 5

如果您使用的是Java 8,请尝试此操作

Arrays.stream(e.getStackTrace())
                .map(s->s.toString())
                .collect(Collectors.joining("\n"));
Run Code Online (Sandbox Code Playgroud)

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

public StackTraceElement[] getStackTrace() {
    return getOurStackTrace().clone();
}
Run Code Online (Sandbox Code Playgroud)

对于StackTraceElement,它将toString提供为:

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

所以只需使用"\n"加入StackTraceElement


sam*_*est 5

Scala版本

def stackTraceToString(e: Exception): String = {
  import java.io.PrintWriter
  val sw = new StringWriter()
  e.printStackTrace(new PrintWriter(sw))
  sw.toString
}
Run Code Online (Sandbox Code Playgroud)