it-swarm.com.de

Wie kann ich einen Stack-Trace in einen String konvertieren?

Was ist der einfachste Weg, um das Ergebnis von Throwable.getStackTrace() in einen String umzuwandeln, der den Stacktrace darstellt?

1316
ripper234

Sie können die folgende Methode verwenden, um einen Exception-Stack-Trace in String zu konvertieren. Diese Klasse ist in Apache commons-lang verfügbar, der am häufigsten verwendeten abhängigen Bibliothek mit vielen beliebten offenen Quellen.

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

921
amar

Verwenden Sie Throwable.printStackTrace(PrintWriter pw) , um den Stack-Trace an einen geeigneten Writer zu senden.

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);
2033
Brian Agnew

Das sollte funktionieren: 

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

Wenn Sie für Android entwickeln, ist die Verwendung dieser Methode viel einfacher:

import Android.util.Log;

String stackTrace = Log.getStackTraceString(exception); 

Das Format ist dasselbe wie getStacktrace, z.

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)
193
Vicky Kapadia

Guavas Throwables Klasse

Wenn Sie über die tatsächliche Throwable-Instanz verfügen, stellt Google GuavaThrowables.getStackTraceAsString() bereit.

Beispiel:

String s = Throwables.getStackTraceAsString ( myException ) ;
110
stumbav

WARNUNG: Enthält keine Ursache (was normalerweise das nützliche Bit ist)

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

Für mich war der sauberste und einfachste Weg:

import Java.util.Arrays;
Arrays.toString(e.getStackTrace());
84
Vladas Diržys
public static String getStackTrace(Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    return sw.toString();
}
29
Akira Yamamoto

Mit dem folgenden Code können Sie das gesamte stackTrace mit einem String-Format abrufen, ohne APIs wie log4J oder sogar Java.util.Logger zu verwenden:

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.
}
25
dumonderic

Hier ist eine Version, die direkt in Code kopiert werden kann:

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

Oder in einem Fangblock

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

Drucken Sie den Stacktrace in einen PrintStream und konvertieren Sie ihn in einen String

// ...

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

    System.out.println(str);
}
11
Baked Inhalf

Stack-Trace als Zeichenfolge drucken

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

Dies ist nützlich, wenn Sie die aktuelle Thread-Stack-Ablaufverfolgung drucken möchten, ohne die Instanz von Throwable zu erstellen. Beachten Sie jedoch, dass das Erstellen einer neuen Throwable und das Abrufen der Stack-Ablaufverfolgung tatsächlich schneller und billiger ist als der Aufruf von Thread.getStackTrace.

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

Ist der einfachste Weg, um das Ergebnis in String zu konvertieren

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

Kotlin

Durch Erweitern der Throwable-Klasse erhalten Sie die String-Eigenschaft error.stackTraceString:

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

Das clevere Schnappen in den ersten Kommentaren war sehr amüsant, aber es hängt wirklich davon ab, was Sie versuchen. Wenn Sie nicht bereits über die richtige Bibliothek verfügen, sind drei Codezeilen (wie in der Antwort von D. Wroblewski) perfekt. OTOH, wenn Sie bereits über die Bibliothek Apache.commons verfügen (wie bei den meisten großen Projekten) ), dann ist die Antwort von Amar kürzer . OK, es kann zehn Minuten dauern, bis Sie die Bibliothek erhalten und korrekt installieren (weniger als eine, wenn Sie wissen, was Sie tun). Aber die Uhr tickt, so dass Sie möglicherweise nicht die Zeit zur Verfügung haben. Jarek Przygódzki hatte einen interessanten Vorbehalt - "Wenn Sie keine verschachtelten Ausnahmen brauchen".

Was aber, wenn ich do die vollständigen Stack-Spuren brauche, verschachtelt und alle? In diesem Fall ist das Geheimnis die Verwendung von getFullStackTrace von Apache.common (siehe http://commons.Apache.org/proper/commons-lang/javadocs/api-2.6/org/Apache/commons/lang/exception/ExceptionUtils) .html # getFullStackTrace% 28Java.lang.Throwable% 29 )

Es hat meinen Speck gerettet. Danke, Amar, für den Hinweis!

9
Tihamer

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

Der Unterschied zu den anderen Antworten besteht darin, dass esautoFlush für die PrintWriter verwendet.

9
IvanRF

Ohne Java.io.* geht das so.

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

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

Und dann enthält die Variable trace Ihren Stack-Trace. Die Ausgabe enthält auch die ursprüngliche Ursache. Die Ausgabe ist identisch mit printStackTrace().

Beispiel: printStackTrace() ergibt:

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)

Die trace-Zeichenfolge gilt, wenn in stdout gedruckt wird.

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)
6
Gala

wenn Sie Java 8 verwenden, versuchen Sie dies

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

sie können den Code für die getStackTrace () - Funktion finden, die von Throwable.Java bereitgestellt wird:

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

und für StackTraceElement gibt es Strings als:

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

Verbinden Sie das StackTraceElement einfach mit "\ n".

5
Pengcheng Zhang

eine Erklärung zu Galas Antwort, die auch die Gründe für die Ausnahme enthalten wird:

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;
}
4
ido flax

Die Lösung ist zum Konvertieren des stackTrace-Arrays in den StringDatentyp. Siehe folgendes Beispiel:

import Java.util.Arrays;

try{

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

Mein Oneliner zum Konvertieren des Stack-Trace in den eingeschlossenen mehrzeiligen String:

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

Einfach an den Logger übergeben "wie er ist".

3

Wenn Sie keine externe Bibliothek verwenden möchten und Sie nicht für Android entwickeln, können Sie eine 'Erweiterungsmethode' erstellen wie folgt:

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

Wenn Sie das Programm ausführen, sieht die Ausgabe ähnlich aus:

Java.lang.ArithmeticException: / by zero
at PrintStackTrace.main(PrintStackTrace.Java:9)
2
Prakhar Nigam

Alte Frage, aber ich möchte nur den speziellen Fall hinzufügen, in dem Sie nicht den gesamten Stapel drucken möchten, Entfernen Sie einige Teile, an denen Sie eigentlich nicht interessiert sind, ausgenommen bestimmte Klassen oder Pakete . 

Anstelle einer PrintWriter verwenden Sie eine 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);

Wo die SelectivePrintWriter-Klasse gegeben ist durch:

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

Bitte beachten Sie, dass diese Klasse leicht angepasst werden kann, um nach Regex, contains oder anderen Kriterien herauszufiltern. Beachten Sie auch, dass es von den Implementierungsdetails von Throwable abhängt (die sich wahrscheinlich nicht ändern werden, aber immer noch).

2
MarcG

Scala-Version

def stackTraceToString(e: Exception): String = {
  import Java.io.PrintWriter
  val sw = new StringWriter()
  e.printStackTrace(new PrintWriter(sw))
  sw.toString
}
1
samthebest

Ich habe vor einiger Zeit einige Methoden dafür geschrieben, also habe ich mir gedacht, warum ich meine zwei Cents nicht darauf werfen sollte.

/** @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;
}

Beispiel:

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

Drucke:

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)
0
Brian_Entei

Warnung: Dies kann ein wenig abwesend sein, aber na ja ...;)

Ich weiß nicht, was die ursprünglichen Plakate Grund war, weil sie die Stapelverfolgung überhaupt als Zeichenkette haben wollten. Wenn die Stack-Ablaufverfolgung in einem SLF4J/Logback-Protokoll enden sollte, wurde jedoch keine Ausnahme ausgegeben. Dies ist, was ich mache:

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
}

Ich mag es, weil es keine externe Bibliothek erfordert (abgesehen von Ihrem Logging-Backend, das ohnehin die meiste Zeit vorhanden sein wird).

0

Einige Optionen

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

  2. Verwenden von Google Guava lib String stackTrace = Throwables.getStackTraceAsString ( myException ) ;

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

0
Eric