Câu hỏi Làm thế nào tôi có thể chuyển đổi một dấu vết ngăn xếp thành một chuỗi?


Cách dễ nhất để chuyển đổi kết quả của Throwable.getStackTrace() vào một chuỗi mô tả stacktrace?


1215
2017-07-19 11:31


gốc


Bởi vì câu trả lời của jqno thực sự sử dụng phương thức Throwable.getStackTrace () mà bạn đã chỉ định trong câu hỏi của mình, trong khi Brian thì không. Thay vào đó, anh ta sử dụng Throwable.printStackTrace (). - Stijn de Witt
Chỉ cần về mọi dự án Java nên bao gồm Apache commons-lang. Nó bao gồm nhiều phương pháp tiện lợi thực hiện các nhu cầu phát triển cực kỳ phổ biến. - Russell Silva
@StijndeWitt Ba dòng mã gần như chắc chắn cần bao thanh toán ra khỏi nơi bạn đã gọi cho họ. Vì bạn không biết đặt chúng ở đâu, chúng sẽ đi vào hộp công cụ tiện ích của bạn với tất cả các đoạn mã hữu ích khác. Chơi lô tô! bạn vừa mới phát minh lại ổi / commons-lang / bất cứ điều gì ... chỉ không tốt lắm. Nhập một thư viện tiện ích hợp lý thay vào đó, và lưu lại phát minh bánh xe. Dấu hiệu thực sự của một người mới là suy nghĩ bạn có thể làm một công việc tốt hơn so với các nhà văn thư viện. - Andrew Spencer
1. Ổi có - Throwables.getStackTraceAsString (e) 2. Apache Commons Lang - ExceptionUtils.getFullStackTrace 3. Viết phương thức tùy chỉnh của riêng chúng ta - user2323036
@AndrewSpencer Tôi không hiểu tại sao các bạn cố gắng hết sức để bash StijndeWitt vì muốn đạt được điều này với một số đoạn nhỏ. Thực sự không có nhiều nguy hiểm khi viết một phương pháp tiện ích nhỏ (tôi không thấy nó như là "SỰ KIỆN ĐÀO TẠO oh nooooo !! Anh ấy nghĩ anh ấy giỏi hơn Apache !!"). Có rất nhiều dự án đặc biệt là trong các ngôn ngữ JVM không phải Java mà thực sự không muốn bao gồm Guava hoặc Commons Lang chỉ để đăng nhập một stacktrace. Tôi viết thư viện Scala & Clojure và chắc chắn sẽ không khiến Apache Commons Lang trở thành phụ thuộc quá độ chỉ cho một phương pháp. - jm0


Các câu trả lời:


Người ta có thể sử dụng phương pháp sau để chuyển đổi Exception ngăn xếp theo dõi String. Lớp này có sẵn trong Apache commons-lang là thư viện phụ thuộc phổ biến nhất với nhiều nguồn mở phổ biến

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


847
2018-01-21 14:39



Một dòng cần thư viện bên ngoài ... - Stijn de Witt
@Stijn - công bằng (tôi đã viết câu trả lời bình chọn cao nhất hiện tại bên dưới) đáng để xem xét commons-lang cho nhiều chức năng hơn - Brian Agnew
@StijndeWitt Commons Lang khá phổ biến. Nó đã có mặt trong hầu hết các dự án / proyects của tôi tại nơi làm việc. - WhyNotHugo
@ Hugo cảm ơn, đã đi để sử dụng StringWriter để tránh thêm một thư viện mới - hóa ra nó đã là một phụ thuộc của 3 phụ thuộc của tôi. Vì vậy, để phần còn lại, kiểm tra xem bạn đã có nó. - Nathanial
@MartinAsenov - theo logic của bạn, bạn sẽ không bao giờ sử dụng thư viện như vậy, phải không? Bạn sẽ không sử dụng nó trừ khi bạn đã sử dụng nó? - Brian Agnew


Sử dụng Throwable.printStackTrace (PrintWriter pw) để gửi dấu vết ngăn xếp tới một người viết thích hợp.

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

1937
2017-07-19 11:36



Nếu bạn không thích bao gồm một thư viện bên ngoài cho một cái gì đó nhỏ và đơn giản như thế này, hãy sử dụng câu trả lời này. - Stijn de Witt
Điều này không cắt theo dõi ngăn xếp, giống như cách printStackTrace (). Tất cả các ngoại lệ trong ngăn xếp đều hiển thị nhưng đối với mỗi ngoại lệ, ngăn xếp có thể được cắt bớt. Bất cứ ai yêu cầu toàn bộ dấu vết nên xem xét điều này. - Laila Agaev
Điều này, khi nó quay ra, là khá nhiều chính xác những gì apache của ExceptionUtils.getStackTrace () phương pháp nào. Hầu như thư thực sự. - ticktock
@BrianAgnew, bạn không nên đóng StringWriter và PrintWriter ? - Muhammad Gelbana
@BrianAgnew, cảm ơn bạn đã trả lời. Nó khiến tôi tò mò và đây là những gì tôi đã tìm thấy: stackoverflow.com/questions/14542535/… - Muhammad Gelbana


Điều này sẽ hoạt động:

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

395
2017-07-19 11:41



Ngắn gọn trong ngữ cảnh java luôn luôn là đồi. Cái đó printStackTrace chỉ nên trả về chuỗi, để lại quyết định về việc in hay không cho người dùng :) - dmitry
printStackTrace in trong giao diện điều khiển là chấp nhận được, nhưng ít nhất một getStackTrace trả về nó như là một String nên có sẵn theo mặc định - Mateus Viccari
Phần nào của điều này là ngắn gọn? Bạn phải xây dựng 2 đối tượng tồn tại không có mục đích nào khác ngoài việc đặt dấu vết ngăn xếp vào một chuỗi. - ArtOfWarfare
@ArtOfWarfare anh rõ ràng đang mỉa mai. - Greg
@dmitry Một phương pháp được gọi là printXXX() nên in XXX. - user207421


Nếu bạn đang phát triển cho Android, một cách dễ dàng hơn là sử dụng điều này:

import android.util.Log;

String stackTrace = Log.getStackTraceString(exception); 

Định dạng giống với getStacktrace, ví dụ:

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)

182
2018-04-30 07:29



Cảm ơn. Trong trường hợp này, ngày và thẻ không được viết trong mỗi hàng như trong printStackTrace (). - CoolMind
Trên thực tế Log.getStackTraceString trong lõi của nó sử dụng đề cập ở trên (D. Wroblewski) StringWriter và Printwriter. - MikeL
Cách dễ nhất để chỉ IN nó trong nhật ký Android là: Log.e("TAG", "My message", new Throwable()); - Erick M. Sprengel


CẢNH BÁO: Không bao gồm nguyên nhân (thường là bit hữu ích!)

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
2017-07-19 11:38



Tôi sẽ đi với phần mở rộng của phương pháp này nếu bạn muốn cắt dấu vết, ví dụ: chuyển một tham số maxLines và chỉ thêm nhiều dòng vào dấu vết - Rich Seller
Các dấu ngoặc đơn sau khi e.getStackTrace bị thiếu. public static String stackTraceToString (Ngoại lệ e) {StringBuilder sb = new StringBuilder (); cho (phần tử StackTraceElement: e.getStackTrace ()) {sb.append (element.toString ()); sb.append ("<br />"); } trả về sb.toString (); } - rlc
Không chắc chắn, nhưng tôi nghĩ rằng điều này sẽ không in dấu vết ngăn xếp của nguyên nhân gốc ngoại lệ. - apoorv020
Dù bạn làm gì, đừng cắt dấu vết. Nó đã xảy ra với tôi nhiều, nhiều lần tôi nhìn vào một dấu vết ngăn xếp trong các bản ghi GlassFish có các bộ phận hữu ích cắt đi. - cayhorstmann
Sử dụng String.format("%n") hoặc một cái gì đó tương tự thay vì "\n" để làm cho DOS làm hài lòng. - ceving


Ổi Throwables lớp học

Nếu bạn có thực tế Throwable ví dụ, Google Guava cung cấp Throwables.getStackTraceAsString().

Thí dụ:

String s = Throwables.getStackTraceAsString ( myException ) ;

96
2018-02-15 10:20





Đối với tôi, cách sạch nhất và dễ nhất là:

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

80
2017-12-15 14:37



Mã là sạch, nhưng đầu ra là không. Bạn phải làm một .replaceAll (",", "\ n") ở cuối. Tuy nhiên, bạn bị mất thụt lề mà printStackTrace đề xuất. - fury
Điều này rất hữu ích khi bạn đăng nhập dấu vết trong một dòng - webjockey


Đoạn mã sau cho phép bạn lấy toàn bộ stackTrace với một String định dạng, không sử dụng API như log4J hoặc thậm chí 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.
}

25
2017-10-24 16:57



ya nhưng một chút cồng kềnh của nó không bạn nghĩ? trong bất kỳ khung khai thác dự án có kích thước hợp lý nào là phải vậy tại sao phải bận tâm - mzzzzb
Điều này là không đưa ra thông báo lỗi trong đầu. có thể được thêm vào - kommradHomer


Lấy cảm hứng từ @Brian Agnew:

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

25
2017-10-03 19:15



Xin chào, tôi chỉ muốn chỉ ra rằng phần nhận xét của câu trả lời được trích dẫn chỉ ra rằng StringWriter và PrintWriterđối tượng phải là closed .... (hoặc tôi chỉ đoán PrintWriter cần phải đóng kể từ khi đóng nó nên đóng StringWriter quá) - Eric
Bằng cảm hứng bạn đã sao chép? Bạn chỉ đặt nó vào một phương pháp ... Đọc câu trả lời ở đây giống như xem "Groundhog Day" - Murmel