etc./StackOverFlow

스택 추적을 문자열로 변환하려면 어떻게 해야 합니까?

청렴결백한 만능 재주꾼 2022. 2. 7. 06:19
반응형

질문자 :ripper234


Throwable.getStackTrace() 의 결과를 스택 추적을 나타내는 문자열로 변환하는 가장 쉬운 방법은 무엇입니까?



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

Brian Agnew

다음 방법을 사용하여 Exception 스택 추적을 String 으로 변환할 수 있습니다. 이 클래스는 많은 인기 있는 오픈 소스가 있는 가장 일반적인 종속 라이브러리인 Apache commons-lang에서 사용할 수 있습니다.

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


amar

이것은 작동해야 합니다:

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

D. Wroblewski

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)

Vicky Kapadia

구아바의 Throwables 클래스

실제 Throwable 인스턴스가 있는 경우 Google Guava Throwables.getStackTraceAsString() 제공합니다.

예시:

 String s = Throwables.getStackTraceAsString ( myException ) ;

stumbav

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

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

jqno

나를 위해 가장 깨끗하고 쉬운 방법은 다음과 같습니다.

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

Vladas Diržys

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

Akira Yamamoto

java.util.Logger 와 같은 API를 사용하지 않고도 String 형식으로 전체 stackTrace를 가져올 수 있습니다.

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

dumonderic

스택 추적을 PrintStream 인쇄한 다음 이를 String 변환합니다.

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

Baked Inhalf

다음은 코드에 직접 복사하여 붙여넣을 수 있는 버전입니다.

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

rouble

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

Ramanan Durairaj

코틀린 >= 1.4

Throwable 에서 내장 함수 stackTraceToString() 을 사용합니다.

코틀린 < 1.4

Throwable 클래스를 확장하면 String 속성 error.stackTraceString 이 제공됩니다.

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

vonox7

스택 추적을 문자열로 인쇄

 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 호출하는 것보다 빠르고 저렴합니다.


Jarek Przygódzki

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

eddyrokr

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

다른 답변과의 차이점은 PrintWriter autoFlush 를 사용 한다는 것입니다.


IvanRF

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 조인하십시오.


Pengcheng Zhang

첫 번째 댓글 세트의 영리한 저격은 매우 재미있었지만 실제로 하려는 작업에 따라 다릅니다. 아직 올바른 라이브러리가 없다면 3줄의 코드(D. Wroblewski의 답변에서와 같이)가 완벽합니다. OTOH, 이미 apache.commons 라이브러리가 있는 경우(대부분의 대규모 프로젝트에서와 같이) Amar의 답변은 더 짧습니다. 좋습니다. 라이브러리를 가져와서 올바르게 설치하는 데 10분 정도 걸릴 수 있습니다. 그러나 시계는 똑딱거리고 있으므로 시간이 없을 수도 있습니다. Jarek Przygó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 )

그것은 내 베이컨을 저장했습니다. 힌트를 주셔서 감사합니다, Amar!


Tihamer

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)

stdout trace 문자열이 유지됩니다.

 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)

Gala

Java 8 Stream API 를 사용하면 다음과 같이 할 수 있습니다.

 Stream .of(throwable.getStackTrace()) .map(StackTraceElement::toString) .collect(Collectors.joining("\n"));

스택 추적 요소의 배열을 가져와 문자열로 변환하고 여러 줄 문자열로 결합합니다.


ivanjermakov

예외의 원인도 포함하는 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; }

ido flax

스칼라 버전

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

samthebest

해결책은 배열의 stackTrace를 문자열 데이터 유형으로 변환하는 것입니다. 다음 예를 참조하십시오.

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

Jorge Santos

외부 라이브러리를 사용하고 싶지 않고 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(); }

Kapé

스택 추적을 동봉된 여러 줄 문자열로 변환하는 내 oneliner:

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

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


Andrey Lebedenko

 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)

Prakhar Nigam

오래된 질문이지만 특정 클래스나 패키지를 제외하고 실제로 관심이 없는 부분을 제거하여 모든 스택을 인쇄하고 싶지 않은 특별한 경우를 추가하고 싶습니다.

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

contains 또는 기타 기준으로 필터링하도록 쉽게 조정할 수 있습니다. 또한 이는 Throwable 구현 세부 정보에 따라 다릅니다(변경될 가능성은 없지만 여전히).


MarcG

경고: 이것은 주제에서 약간 벗어날 수 있지만 오 글쎄... ;)

원래 포스터의 이유 가 스택 추적을 처음에 문자열로 원하는 이유가 무엇인지 모르겠습니다. 스택 추적이 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 }

외부 라이브러리가 필요하지 않기 때문에 마음에 듭니다(물론 대부분의 시간 동안 사용할 로깅 백엔드 제외).


Alexander Wessel

몇 가지 옵션

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

  2. Google 구아바 라이브러리 사용하기 String stackTrace = Throwables.getStackTraceAsString ( myException ) ;

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


Eric

나는 얼마 전에 이에 대한 몇 가지 방법을 썼으므로 여기에 내 2센트를 던지지 않는 이유를 생각했습니다.

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

Brian_Entei

출처 : http:www.stackoverflow.com/questions/1149703/how-can-i-convert-a-stack-trace-to-a-string

반응형