Come visualizzare messaggi lunghi in logcat


99

Sto cercando di visualizzare un messaggio lungo su logcat. Se la lunghezza del messaggio è superiore a 1000 caratteri, viene interrotto.

Qual è il meccanismo per mostrare tutti i caratteri del messaggio lungo in logcat?


6
Ricevo risposta dal server come una lunga stringa.
Vasu

1
Anche allora perché dovresti voler stampare l'intera stringa, scriverla su un file o database e visualizzarla lì - se è per il debug
Rahul Choudhary

copia la tua stringa logcat e incollala nel notpad, puoi vedere la lunghezza intera 1000 della stringa.
ilango j

Risposte:


149

Se logcat sta limitando la lunghezza a 1000, puoi dividere la stringa che desideri registrare con String.subString () e registrarla in pezzi. Per esempio:

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

Log cat stampa solo la metà della risposta .. come posso ottenere la lunghezza dell'intera risposta. hai detto che veryLongString.length () ma qui è stampata solo metà della risposta quando stampo il risultato json in log cat
Vasu

Ma nella console iPhone ricevo l'intera stringa di risposta
Vasu

puoi controllare la lunghezza della risposta scrivendo length () nel log. Se questo valore non è quello che ti aspettavi, il problema potrebbe non riguardare la registrazione.
spatulamania

3
Non riesco a credere che Android lo renda così difficile!
Alston

1
Penso che questo codice registrerà una voce di log vuota in più alla fine, se veryLongString.length()è un multiplo di maxLogSize. Forse cambia <=in <.
LarsH

29

In seguito alla risposta di spatulamania, ho scritto una classe wrapper che gestisce questo per te. Devi solo modificare l'importazione e registrerà tutto

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

}

23

Questo si basa sulla risposta di spatulamania, è un po 'più succinto e non aggiungerà un messaggio di log vuoto alla fine:

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

Grazie. Non sono raccomandati più di 3000 simboli, io lo uso.
CoolMind

9

Ecco come fa OkHttp con 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 è 4000.

Qui usa Log.d (debug) e il tag "OkHttp" hardcoded.

Divide il registro a nuove righe o quando raggiunge la lunghezza massima.

Questa classe di seguito è una classe helper che puoi usare (se hai il supporto lambda lancia Jack & Jill o retrolambda) per fare la stessa cosa che OkHttp fa su qualsiasi registro:

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

Lo stavo cercando da solo nel loro codice ma non sono riuscito a trovarlo. Grazie.
bug si verificano

8

Prova questo pezzo di codice per mostrare un messaggio lungo in logcat.

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

6
quando un semplice ciclo sarà sufficiente, perché usare la ricorsione.
pellucide

3
Sono un fan della ricorsione poiché trovo la leggibilità e il riutilizzo del codice eccezionali. Tuttavia, questa ricorsione in coda può creare rapidamente stack frame se il compilatore non li ottimizza (cosa che non credo faccia lo studio Android). Ciò significa che se hai un messaggio sostanzialmente lungo che causa un pluribus di chiamate ricorsive puoi facilmente creare uno StackOverflowError.
Luca

3

Per non ridurre al minimo la divisione delle righe tra i messaggi di registro, prendo la stringa grande e registro ogni riga separatamente.

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

1

Ecco una versione di Kotlin per la risposta @spatulamania (specialmente per i popoli pigri / intelligenti):

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

1

Considero Timber una buona opzione per questo problema. Timber divide e stampa automaticamente blocchi di messaggio in logcat.

https://github.com/JakeWharton/timber

Puoi vedere l'implementazione del metodo di log nella classe statica timber.log.Timber.DebugTree.


0

se si stampa la stringa json, è possibile utilizzare il codice seguente

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

codice completo

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

risultato in anteprima


-2

Per una soluzione semplice, usa l' opzione Usa avvolgimento morbido nel punto di attacco sottostante n. 4 opzioni potrebbero aiutarti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.