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


当前回答

如果你不想使用外部库,而且你不是为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();
}

其他回答

如果你不想使用外部库,而且你不是为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();
}

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

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

请注意,这个类可能很容易被Regex、contains或其他条件过滤掉。还要注意,这取决于可丢弃的实现细节(不太可能改变,但仍然如此)。

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

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

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

然后跟踪变量保存堆栈跟踪。输出也包含初始原因,输出与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)

当打印到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)

番石榴的丢弃类

如果您有实际的Throwables实例,GoogleGuava提供Throwables.getStackTraceAsString()。

例子:

String s = Throwables.getStackTraceAsString ( myException ) ;
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});