So zeigen Sie lange Nachrichten in logcat an

99

Ich versuche, eine lange Nachricht auf logcat anzuzeigen. Wenn die Länge der Nachricht mehr als 1000 Zeichen beträgt, wird sie unterbrochen.

Was ist der Mechanismus, um alle Zeichen einer langen Nachricht in logcat anzuzeigen?

Vasu
quelle
6
Ich erhalte eine Antwort vom Server als lange Zeichenfolge.
Vasu
1
Selbst dann, warum sollten Sie die gesamte Zeichenfolge drucken, in eine Datei oder Datenbank schreiben und dort - wenn zum Debuggen
Rahul Choudhary
Kopieren Sie Ihre Logcat-Zeichenfolge und fügen Sie sie in das Notpad ein. Sie können die gesamte Länge der Zeichenfolge von 1000 sehen.
Ilango J
stackoverflow.com/questions/8888654/…
Ciro Santilli 法轮功 冠状 冠状. 六四

Antworten:

149

Wenn logcat die Länge auf 1000 begrenzt, können Sie die zu protokollierende Zeichenfolge mit String.subString () teilen und in Teilen protokollieren. Beispielsweise:

int maxLogSize = 1000;
for(int i = 0; i <= veryLongString.length() / maxLogSize; i++) {
    int start = i * maxLogSize;
    int end = (i+1) * maxLogSize;
    end = end > veryLongString.length() ? veryLongString.length() : end;
    Log.v(TAG, veryLongString.substring(start, end));
}
Spatulamania
quelle
Log Cat druckt nur die Hälfte der Antwort. Wie kann ich die Länge der gesamten Antwort ermitteln? Sie sagten, dass sehr LongString.length (), aber hier ist es nur die Hälfte der Antwort gedruckt, wenn ich das JSON-Ergebnis in Log Cat
drucke
Aber in der iPhone-Konsole bekomme ich die gesamte Antwortzeichenfolge
Vasu
Sie können die Länge der Antwort überprüfen, indem Sie length () in das Protokoll schreiben. Wenn dieser Wert nicht Ihren Erwartungen entspricht, liegt das Problem möglicherweise nicht bei der Protokollierung.
Spatulamania
3
Ich kann nicht glauben, dass Android es so schwer macht!
Alston
1
Ich denke, dieser Code protokolliert am Ende einen zusätzlichen, leeren Protokolleintrag, wenn veryLongString.length()es sich um ein Vielfaches von handelt maxLogSize. Vielleicht ändern Sie das <=zu <.
LarsH
29

Als Folge der Antwort von Spatulamania habe ich eine Wrapper-Klasse geschrieben, die dies für Sie erledigt. Sie müssen nur den Import ändern und es wird alles protokolliert

public class Log {

    public static void d(String TAG, String message) {
        int maxLogSize = 2000;
        for(int i = 0; i <= message.length() / maxLogSize; i++) {
            int start = i * maxLogSize;
            int end = (i+1) * maxLogSize;
            end = end > message.length() ? message.length() : end;
            android.util.Log.d(TAG, message.substring(start, end));
        }
    }

}
Jiduva
quelle
23

Dies baut auf der Antwort von Spatulamania auf, ist etwas prägnanter und fügt am Ende keine leere Protokollnachricht hinzu:

final int chunkSize = 2048;
for (int i = 0; i < s.length(); i += chunkSize) {
    Log.d(TAG, s.substring(i, Math.min(s.length(), i + chunkSize)));
}
LarsH
quelle
Vielen Dank. Mehr als 3000 Symbole werden nicht empfohlen, ich benutze sie.
CoolMind
9

So macht es OkHttp mit HttpLoggingInterceptor:

public void log(String message) {
  // Split by line, then ensure each line can fit into Log's maximum length.
  for (int i = 0, length = message.length(); i < length; i++) {
    int newline = message.indexOf('\n', i);
    newline = newline != -1 ? newline : length;
    do {
      int end = Math.min(newline, i + MAX_LOG_LENGTH);
      Log.d("OkHttp", message.substring(i, end));
      i = end;
    } while (i < newline);
  }
}

MAX_LOG_LENGTH ist 4000.

Hier wird Log.d (Debug) und das fest codierte "OkHttp" -Tag verwendet.

Das Protokoll wird bei Zeilenumbrüchen oder bei Erreichen der maximalen Länge aufgeteilt.

Diese Klasse unten ist eine Hilfsklasse, die Sie verwenden können (wenn Sie Lambda-Unterstützung haben, werfen Sie Jack & Jill oder Retrolambda), um dasselbe zu tun, was OkHttp in jedem Protokoll tut:

/**
 * Help printing logs splitting text on new line and creating multiple logs for too long texts
 */

public class LogHelper {

    private static final int MAX_LOG_LENGTH = 4000;

    public static void v(@NonNull String tag, @Nullable String message) {
        log(message, line -> Log.v(tag, line));
    }

    public static void d(@NonNull String tag, @Nullable String message) {
        log(message, line -> Log.d(tag, line));
    }

    public static void i(@NonNull String tag, @Nullable String message) {
        log(message, line -> Log.i(tag, line));
    }

    public static void w(@NonNull String tag, @Nullable String message) {
        log(message, line -> Log.w(tag, line));
    }

    public static void e(@NonNull String tag, @Nullable String message) {
        log(message, line -> Log.e(tag, line));
    }

    public static void v(@NonNull String tag, @Nullable String message, @Nullable Throwable throwable) {
        log(message, throwable, line -> Log.v(tag, line));
    }

    public static void d(@NonNull String tag, @Nullable String message, @Nullable Throwable throwable) {
        log(message, throwable, line -> Log.d(tag, line));
    }

    public static void i(@NonNull String tag, @Nullable String message, @Nullable Throwable throwable) {
        log(message, throwable, line -> Log.i(tag, line));
    }

    public static void w(@NonNull String tag, @Nullable String message, @Nullable Throwable throwable) {
        log(message, throwable, line -> Log.w(tag, line));
    }

    public static void e(@NonNull String tag, @Nullable String message, @Nullable Throwable throwable) {
        log(message, throwable, line -> Log.e(tag, line));
    }

    private static void log(@Nullable String message, @NonNull LogCB callback) {
        if (message == null) {
            callback.log("null");
            return;
        }
        // Split by line, then ensure each line can fit into Log's maximum length.
        for (int i = 0, length = message.length(); i < length; i++) {
            int newline = message.indexOf('\n', i);
            newline = newline != -1 ? newline : length;
            do {
                int end = Math.min(newline, i + MAX_LOG_LENGTH);
                callback.log(message.substring(i, end));
                i = end;
            } while (i < newline);
        }
    }

    private static void log(@Nullable String message, @Nullable Throwable throwable, @NonNull LogCB callback) {
        if (throwable == null) {
            log(message, callback);
            return;
        }
        if (message != null) {
            log(message + "\n" + Log.getStackTraceString(throwable), callback);
        } else {
            log(Log.getStackTraceString(throwable), callback);
        }
    }

    private interface LogCB {
        void log(@NonNull String message);
    }
}
Daniele Segato
quelle
Ich habe es selbst in ihrem Code gesucht, konnte es aber nicht finden. Danke dir.
Bugs passieren
8

Versuchen Sie diesen Code, um eine lange Nachricht in logcat anzuzeigen.

public void logLargeString(String str) {
    if(str.length() > 3000) {
        Log.i(TAG, str.substring(0, 3000));
        logLargeString(str.substring(3000));
    } else {
        Log.i(TAG, str); // continuation
    }
}
Mani
quelle
6
Wenn eine einfache Schleife ausreicht, warum dann Rekursion verwenden?
Pellucide
3
Ich bin ein Fan von Rekursion, da ich die Lesbarkeit und Wiederverwendung von Code großartig finde. Diese Tail-End-Rekursion kann jedoch schnell Stack-Frames aufbauen, wenn Ihr Compiler sie nicht optimiert (was meiner Meinung nach im Android Studio nicht der Fall ist). Dies bedeutet, dass Sie einen StackOverflowError erstellen können, wenn Sie eine sehr lange Nachricht haben, die eine Vielzahl rekursiver Aufrufe verursacht.
Luke
3

Um die Aufteilung der Zeilen auf Protokollnachrichten nicht zu minimieren, nehme ich die große Zeichenfolge und protokolliere jede Zeile separat.

void logMultilineString(String data) {
    for (String line : data.split("\n")) {
        logLargeString(line);
    }
}

void logLargeString(String data) {
    final int CHUNK_SIZE = 4076;  // Typical max logcat payload.
    int offset = 0;
    while (offset + CHUNK_SIZE <= data.length()) {
        Log.d(TAG, data.substring(offset, offset += CHUNK_SIZE));
    }
    if (offset < data.length()) {
        Log.d(TAG, data.substring(offset));
    }
}
vonWippersnap
quelle
1

Hier ist eine Kotlin-Version für die Antwort von @spatulamania (insbesondere für faule / kluge Leute):

val maxLogSize = 1000
val stringLength = yourString.length
for (i in 0..stringLength / maxLogSize) {
    val start = i * maxLogSize
    var end = (i + 1) * maxLogSize
    end = if (end > yourString.length) yourString.length else end
    Log.v("YOURTAG", yourString.substring(start, end))
}
Filipe Brito
quelle
1

Ich halte Timber für eine gute Option für dieses Problem. Timber teilt und druckt automatisch Nachrichtenblöcke in logcat.

https://github.com/JakeWharton/timber

Sie können die Implementierung der Protokollmethode in der statischen Klasse timber.log.Timber.DebugTree sehen.

Jaelson Wagner
quelle
0

Wenn Sie eine JSON-Zeichenfolge drucken, können Sie den folgenden Code verwenden

    @JvmStatic
    fun j(level: Int, tag: String? = null, msg: String) {
        if (debug) {
            if (TextUtils.isEmpty(msg)) {
                p(level, tag, msg)
            } else {
                val message: String
                message = try {
                    when {
                        msg.startsWith("{") -> {
                            val jsonObject = JSONObject(msg)
                            jsonObject.toString(4)
                        }
                        msg.startsWith("[") -> {
                            val jsonArray = JSONArray(msg)
                            jsonArray.toString(4)
                        }
                        else -> msg
                    }
                } catch (e: JSONException) {
                    e.printStackTrace()
                    msg
                }
                p(level, tag, "╔═══════════════════════════════════════════════════════════════════════════════════════", false)
                val lines = message.split(LINE_SEPARATOR.toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                for (line in lines) {
                    p(level, tag, "║ $line", false)
                }
                p(level, tag, "╚═══════════════════════════════════════════════════════════════════════════════════════", false)
            }
        }
    }

vollständiger Code

CXLogUtil.j ("json-tag", "{}")

Vorschau Ergebnis

Michael Mao
quelle
-2

Verwenden Sie für eine einfache Lösung die Option " Soft Wrap verwenden " unter den Optionen "Anhängepunkt Nr. 4".

Mohit Suthar
quelle