Почему мой IOException не печатает правильную стек в JUnit? [Дубликат]

Ошибки округления с плавающей запятой. 0,1 не могут быть представлены точно в базе-2, как в базе-10, из-за недостающего простого коэффициента 5. Так же, как 1/3 принимает бесконечное число цифр для представления в десятичной форме, но составляет «0,1» в базе-3, 0.1 принимает бесконечное число цифр в базе-2, где оно не находится в базе-10. И компьютеры не имеют бесконечного объема памяти.

1223
задан james.garriss 11 March 2016 в 21:04
поделиться

26 ответов

Для преобразования трассировки стека Exception в String можно использовать следующий метод. Этот класс доступен в Apache commons-lang, который является наиболее распространенной зависимой библиотекой со многими популярными открытыми источниками

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

851
ответ дан amar 27 August 2018 в 18:31
поделиться

Вдохновленный @Brian Agnew:

public static String getStackTrace(Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    return sw.toString();
}
25
ответ дан Akira Yamamoto 27 August 2018 в 18:31
поделиться

Предупреждение: это может быть немного не по теме, но хорошо ...;)

Я не знаю, что оригинальные плакаты 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
}

Мне это нравится, потому что он не требует внешней библиотеки (другой чем ваш бэкэнд ведения журнала, который будет в большинстве случаев в любом случае, конечно.)

0
ответ дан Alexander Wessel 27 August 2018 в 18:31
поделиться

Мой oneliner для преобразования трассировки стека в прилагаемую многострочную строку:

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

Легко перейти к регистратору «как есть».

2
ответ дан Andrey Lebedenko 27 August 2018 в 18:31
поделиться

Распечатайте 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);
}
8
ответ дан Baked Inhalf 27 August 2018 в 18:31
поделиться

Если вы не хотите использовать внешнюю библиотеку, и вы не разрабатываете для Android , вы можете создать метод 'extension' следующим образом:

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
ответ дан Community 27 August 2018 в 18:31
поделиться

Это должно работать:

StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
399
ответ дан D. Wroblewski 27 August 2018 в 18:31
поделиться

Throwables класс Guava

Если у вас есть фактический экземпляр Throwable, Google Guava предоставляет Throwables.getStackTraceAsString() .

Пример:

String s = Throwables.getStackTraceAsString ( myException ) ;
97
ответ дан dimo414 27 August 2018 в 18:31
поделиться
private String getCurrentStackTraceString() {
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    return Arrays.stream(stackTrace).map(StackTraceElement::toString)
            .collect(Collectors.joining("\n"));
}
8
ответ дан eddyrokr 27 August 2018 в 18:31
поделиться

Используйте 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);
1943
ответ дан Eng.Fouad 27 August 2018 в 18:31
поделиться

Без 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)
6
ответ дан Gala 27 August 2018 в 18:31
поделиться

Старый вопрос, но я хотел бы просто добавить специальный случай, когда вы не хотите печатать весь стек, удалив некоторые части, на которых вас фактически не интересуют, исключая определенные классы или пакеты.

Вместо 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 (вряд ли изменится, но все же).

2
ответ дан gil.fernandes 27 August 2018 в 18:31
поделиться

расширение ответа Галы, в которое также будут включены причины исключения:

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 27 August 2018 в 18:31
поделиться

Код из 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.

6
ответ дан IvanRF 27 August 2018 в 18:31
поделиться

Трассировка стека стека в строку

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.

10
ответ дан Jarek Przygódzki 27 August 2018 в 18:31
поделиться

Решение состоит в том, чтобы преобразовать stackTrace для массива в строковый тип данных. См. Следующий пример:

import java.util.Arrays;

try{

}catch(Exception ex){
    String stack = Arrays.toString(ex.getStackTrace());
    System.out.println("stack "+ stack);
}
1
ответ дан jorge santos 27 August 2018 в 18:31
поделиться

Следующий код позволяет вам получить весь стекTrace с форматом String без использования API, таких как log4J или даже 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.
}
24
ответ дан Murilo Vasconcelos 27 August 2018 в 18:31
поделиться
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});
9
ответ дан Panu Haaramo 27 August 2018 в 18:31
поделиться

, если вы используете java 8, попробуйте это

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

, вы можете найти код для функции getStackTrace (), предоставленный Throwable.java как:

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

Так что просто присоедините StackTraceElement к «\n»

2
ответ дан Pengcheng Zhang 27 August 2018 в 18:31
поделиться

Если вы разрабатываете 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)
< / BLOCKQUOTE>
184
ответ дан Pokechu22 27 August 2018 в 18:31
поделиться

Вот версия, которая скопируется непосредственно в код:

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

} catch (Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    logger.info("Current stack trace is:\n" + sw.toString());
}
18
ответ дан rouble 27 August 2018 в 18:31
поделиться

ПРЕДУПРЕЖДЕНИЕ: не включает причину (обычно это полезный бит!) [/ ​​g0]

public String stackTraceToString(Throwable e) {
    StringBuilder sb = new StringBuilder();
    for (StackTraceElement element : e.getStackTrace()) {
        sb.append(element.toString());
        sb.append("\n");
    }
    return sb.toString();
}
106
ответ дан samthebest 27 August 2018 в 18:31
поделиться

Умный снайпер в первом комплекте комментариев был очень забавным, но это действительно зависит от того, что вы пытаетесь сделать. Если у вас еще нет правильной библиотеки, то 3 строки кода (как в ответе Д. Вроблевски) идеальны. OTOH, если у вас уже есть библиотека apache.commons (как это делают большинство крупных проектов), ответ Амара будет короче. Хорошо, вам понадобится десять минут, чтобы получить библиотеку и установить ее правильно (менее одного, если вы знаете, что делаете). Но часы тикают, поэтому у вас может не хватить времени. Jarek Przygódzki имел интересное предупреждение: «Если вам не нужны вложенные исключения».

Но что делать, если я do нуждается в полных стеках стека, вложенных и всех? В этом случае секрет заключается в использовании getFullStackTrace apache.common (см. http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ ExceptionUtils.html # getFullStackTrace% 28java.lang.Throwable% 29 )

Он спас мой бекон. Спасибо, Амар, за подсказку!

5
ответ дан Tihamer 27 August 2018 в 18:31
поделиться

Для меня самый чистый и простой способ:

import java.util.Arrays;
Arrays.toString(e.getStackTrace());
80
ответ дан Vladas Diržys 27 August 2018 в 18:31
поделиться

Kotlin

Расширение класса Throwable даст вам свойство String error.stackTraceString:

val Throwable.stackTraceString: String
  get() {
    val sw = StringWriter()
    val pw = PrintWriter(sw)
    this.printStackTrace(pw)
    return sw.toString()
  }
7
ответ дан vonox7 27 August 2018 в 18:31
поделиться

Используйте exp.printStackTrace() для отображения стека вашего исключения.

try {
   int zero = 1 - 1;
   int a = 1/zero;
} catch (Exception e) {
    e.printStackTrace();
}
-1
ответ дан Михаил Чеботарев 27 August 2018 в 18:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: