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

时间:2009-07-19 11:31:44

标签: java stack-trace tostring

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

31 个答案:

答案 0 :(得分:2080)

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

答案 1 :(得分:954)

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

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

答案 2 :(得分:431)

这应该有效:

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

答案 3 :(得分:202)

如果您正在为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)

答案 4 :(得分:116)

Guava的Throwables

如果您拥有实际的Throwable个实例,则Google Guava会提供Throwables.getStackTraceAsString()

示例:

String s = Throwables.getStackTraceAsString ( myException ) ;

答案 5 :(得分:110)

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

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

答案 6 :(得分:86)

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

import java.util.Arrays;
Arrays.toString(e.getStackTrace());

答案 7 :(得分:29)

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

答案 8 :(得分:25)

以下代码允许您使用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.
}

答案 9 :(得分: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());

或者,在一个捕获块中

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

答案 10 :(得分:11)

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

{{1}}

答案 11 :(得分: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);
        }
    }
}

当您想要打印当前线程堆栈跟踪而不创建Throwable实例时,它非常有用 - 但请注意,创建新Throwable并从中获取堆栈跟踪实际上比调用{{{{{}}更快,更便宜1}}。

答案 12 :(得分:10)

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

答案 13 :(得分:10)

Arrays.toString(thrown.getStackTrace())

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

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

答案 14 :(得分: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

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

答案 15 :(得分: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();
}

与其他答案的区别在于autoFlush上使用 PrintWriter

答案 16 :(得分:9)

科特林

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

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

答案 17 :(得分:6)

没有$reindexed = array(); foreach ($courses as $values) { $reindexed[$values['course_id']] = $values; } 就可以这样做。

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

答案 18 :(得分:5)

如果你使用的是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即可

答案 19 :(得分:4)

对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;
}

答案 20 :(得分:3)

我的oneliner将堆栈跟踪转换为包含的多行字符串:

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

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

答案 21 :(得分:3)

解决方法是将数组的stackTrace转换为字符串数据类型。请参阅以下示例:

import java.util.Arrays;

try{

}catch(Exception ex){
    String stack = Arrays.toString(ex.getStackTrace());
    System.out.println("stack "+ stack);
}

答案 22 :(得分:2)

老问题,但我想添加一个特殊情况,你不想打印所有堆栈, 删除某些您实际上并不感兴趣的部分,不包括某些类或包。

而不是PrintWriter使用SelectivePrintWriter

// 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或其他标准进行过滤。另请注意,这取决于Throwable实施细节(不太可能改变,但仍然如此)。

答案 23 :(得分:2)

如果您不想使用外部资源库并且尚未开发for Android,则可以像这样创建'extension' method

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();
}

答案 24 :(得分:2)

 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)

答案 25 :(得分:2)

我想知道为什么没人提到SQL> desc tukc Name Null? Type ----------- ----- ------------------ OBJECT_NAME VARCHAR2(128 CHAR) OBJECT_ID NUMBER SQL> SQL> create or replace view tv as 2 select t.object_name 3 from tukc t join all_objects o on (t.object_id=o.object_id) 4 union all 5 select t.object_name 6 from tukc t join all_objects o on (t.object_id=o.object_id) 7 ; View TV created. SQL> desc tv Name Null? Type ----------- ----- ------------------ OBJECT_NAME VARCHAR2(128 CHAR)

对我来说,这是将stacktrace及其所有原因转储到最后的最方便的方法:

ExceptionUtils.getStackFrames(exception)

答案 26 :(得分:1)

Scala版本

stringify

答案 27 :(得分:1)

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

System.IO.File.Move("oldfilename", "newfilename");

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

答案 28 :(得分:0)

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

我不知道原始海报 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
}

我喜欢它,因为它不需要外部库(除了你的日志记录后端,当然,大多数时候它都会在适当的位置使用)。

答案 29 :(得分:0)

很少有选择

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

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

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

答案 30 :(得分:0)

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

/** @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)