문제

결과를 변환하는 가장 쉬운 방법은 무엇입니까? Throwable.getStackTrace() 스택 트레이스를 묘사하는 문자열로?

도움이 되었습니까?

해결책

다음 방법을 사용하여 변환 할 수 있습니다 Exception 추적을 스택으로 쌓습니다 String. 이 수업은 이용 가능합니다 인기있는 오픈 소스가 많은 가장 일반적인 종속 라이브러리 인 Apache Commons-Lang

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

다른 팁

사용 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);

이것은 작동해야합니다 :

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

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)

Guava's Throwables class

If you have the actual Throwable instance, Google Guava provides Throwables.getStackTraceAsString().

Example:

String s = Throwables.getStackTraceAsString ( myException ) ;

경고 : 원인은 포함되지 않습니다 (일반적으로 유용한 비트입니다!)

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

나에게 가장 깨끗하고 쉬운 방법은 다음과 같습니다.

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

다음 코드를 사용하면 전체 스택 트레이스를 String 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.
}

다음은 코드에 직접 복사 할 수있는 버전입니다.

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

스택 추적을 a에 인쇄하십시오 PrintStream, 그런 다음 a로 변환하십시오 String:

// ...

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

    System.out.println(str);
}

스택 추적 인쇄 스트링

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.

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

코 틀린

Throwable 클래스를 연장하면 문자열 속성이 제공됩니다. error.stackTraceString:

val Throwable.stackTraceString: String
  get() {
    val sw = StringWriter()
    val pw = PrintWriter(sw)
    this.printStackTrace(pw)
    return sw.toString()
  }
private String getCurrentStackTraceString() {
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    return Arrays.stream(stackTrace).map(StackTraceElement::toString)
            .collect(Collectors.joining("\n"));
}

첫 번째 의견 세트에서 영리한 저격은 매우 재미 있었지만 실제로는 당신이하려는 일에 달려 있습니다. 아직 올바른 라이브러리가 없다면 D. Wroblewski의 답변에서와 같이 3 줄의 코드가 완벽합니다. Otoh, 이미 Apache.commons 라이브러리가 있다면 (대부분의 대규모 프로젝트와 같이) Amar의 대답은 짧습니다. 좋아, 라이브러리를 가져 와서 올바르게 설치하는 데 10 분이 걸릴 수 있습니다 (당신이하고있는 일을 아는 경우 1보다 작음). 그러나 시계가 똑딱 거리고 있으므로 여분의 시간이 없을 수도 있습니다. Jarek Przygódzki는 흥미로운 경고를 가졌습니다. "중첩 된 예외가 필요하지 않은 경우".

하지만 내가 만약 내가 어떨까요? 하다 전체 스택 추적, 중첩 및 모든 것이 필요하십니까? 이 경우 비밀은 Apache.Common의 GetFullStackTrace를 사용하는 것입니다 ( http://commons.apache.org/proper/commons/javadocs/api-2.6/org/apache/commons/lang/exception/exceptionutils.html#getfullstacktrace%28java.lang.throwable%29)

그것은 내 베이컨을 구했습니다. 감사합니다, Amar, 힌트!

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

다른 대답과의 차이점은 그 것입니다 사용합니다 autoFlushPrintWriter.

없이 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)

Java 8을 사용하는 경우 시도해보십시오

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

코드를 찾을 수 있습니다 getStackTrace() 제공 한 기능 Throwable.java 처럼 :

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

그리고 StackTraceElement, IT 제공자 toString() 처럼:

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

그냥 가입하십시오 StackTraceElement " n"으로.

예외의 원인도 포함 할 갈라의 답변에 대한 exapansion :

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

스택 추적을 동봉 된 멀티 라인 문자열로 변환하는 내 oneLiner :

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

"그대로"로거로 전달하기 쉽습니다.

해결책은입니다 배열의 스택 트레이스를 문자열로 변환합니다 데이터 형식. 다음 예를 참조하십시오.

import java.util.Arrays;

try{

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

스칼라 버전

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

외부 라이브러리를 사용하고 싶지 않고 개발하지 않으면 안드로이드의 경우, 당신은 당신을 만들 수 있습니다 '확장'방법 이와 같이:

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

오래된 질문이지만, 나는 당신이 당신의 특별한 케이스를 추가하고 싶습니다. 모든 스택을 인쇄하고 싶지 않습니다, 특정 부품을 제거하면 특정 클래스 나 패키지를 제외하고 실제로 관심이 없습니다.

대신 a PrintWriter a 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 구현 세부 사항 (변경되지는 않지만 여전히).

 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)

경고 : 이것은 약간의 주제일지도 모르지만 오 잘 ...;)

원래 포스터가 무엇인지 모르겠습니다 이유 스택 추적을 처음에 문자열로 원한 것입니다. 스택 추적이 SLF4J/로그백 로그로 끝나야하지만 여기서 예외는 아니에도하지 않아야합니다.

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
}

외부 라이브러리가 필요하지 않기 때문에 좋아합니다 (물론 대부분의 경우 로깅 백엔드를 제외하고는 대부분의 경우).

몇 가지 옵션

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

  2. Google Guava Lib 사용String stackTrace = Throwables.getStackTraceAsString ( myException ) ;

  3. org.apache.commons.lang.exception.exception.getstacktrace (Throwable)

나는 얼마 전에 이것을 위해 몇 가지 방법을 썼다.

/** @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)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top