2012-06-06 31 views
12

Tengo un QByteArray para almacenar datos recibidos de un GPS, que es parte binario y parte ASCII. Quiero saber de propuestas de depuración saber lo que está siendo recibida, así que estoy escribiendo un qDebug así:qDebug no está imprimiendo un QByteArray completo que contiene datos binarios

//QByteArray buffer; 
//... 
qDebug() << "GNSS msg (" << buffer.size() << "): " << buffer; 

Y consigo mensajes como este en la consola:

GNSS msg (1774): "ygnnsdgk...(many data)..PR085hlHJGOLH 
(more data into a new line, which is OK because it is a new GNSS sentence and 
probably has a \n at the end of each one) blablabla... 

Pero de repente recibo una nueva iteración de impresión. Los datos no se han borrado todavía, se ha agregado. Entonces, el nuevo tamaño del mensaje es, por ejemplo, 3204, más grande que la impresión anterior, obviamente. Pero imprime exactamente lo mismo (pero con el nuevo tamaño 3204 entre paréntesis). No hay nuevos datos se imprimen, lo mismo que el mensaje anterior tenía:

GNSS msg (3204): "ygnnsdgk...(many data)..PR085hlHJGOLH 
(more data into a new line, which is OK because it is a new GNSS sentence and 
probably has a \n at the end of each one) blablabla... 

supongo qDebug deja de imprimir, ya que tiene un límite, o porque llega un carácter de terminación o algo por el estilo, pero yo sólo soy adivinación.

¿Alguna ayuda o explicación para este comportamiento?

Respuesta

23

Solución/Solución:

De hecho, la salida de qDebug()QByteArray se trunca a un personaje '\0'. Esto no tiene nada que ver con QByteArray; incluso no se puede generar un carácter '\ 0' con qDebug(). Para una explicación, ver a continuación.

QByteArray buffer; 
buffer.append("hello"); 
buffer.append('\0'); 
buffer.append("world"); 

qDebug() << "GNSS msg (" << buffer.size() << "): " << buffer; 

Salida:

GNSS msg (11): "hello 

Incluso los argumentos siguientes son ignorados:

qDebug() << "hello" << '\0' << "world"; 

Salida:

hello 

Puede solucionar este "problema", sustituyendo la personajes especiales en tu byte matriz antes de la depuración de ellas:

QByteArray dbg = buffer; // create a copy to not alter the buffer itself 
dbg.replace('\\', "\\\\"); // escape the backslash itself 
dbg.replace('\0', "\\0"); // get rid of 0 characters 
dbg.replace('"', "\\\""); // more special characters as you like 

qDebug() << "GNSS msg (" << buffer.size() << "): " << dbg; // not dbg.size()! 

Salida:

GNSS msg (11): "hello\0world" 

Entonces ¿por qué sucede esto? ¿Por qué no puedo generar un '\0' usando qDebug()?

Vamos a sumergirnos en el código interno de Qt para averiguar qué hace qDebug(). Los siguientes fragmentos de código provienen del código fuente de Qt 4.8.0.

Este método se llama cuando se hace qDebug() << buffer:

inline QDebug &operator<<(const QByteArray & t) { 
    stream->ts << '\"' << t << '\"'; return maybeSpace(); 
} 

El stream->ts anterior es de tipo QTextStream, que convierte la QByteArray en un QString:

QTextStream &QTextStream::operator<<(const QByteArray &array) 
{ 
    Q_D(QTextStream); 
    CHECK_VALID_STREAM(*this); 
    // Here, Qt constructs a QString from the binary data. Until now, 
    // the '\0' and following data is still captured. 
    d->putString(QString::fromAscii(array.constData(), array.length())); 
    return *this; 
} 

Como se puede ver, d->putString(QString) se llama (el tipo de d es la clase privada interna de la secuencia de texto), que llama al write(QString) después de hacer algo de relleno para campos de ancho constante. Me omitir el código de putString(QString) y saltar directamente en d->write(QString), que se define así:

inline void QTextStreamPrivate::write(const QString &data) 
{ 
    if (string) { 
     string->append(data); 
    } else { 
     writeBuffer += data; 
     if (writeBuffer.size() > QTEXTSTREAM_BUFFERSIZE) 
      flushWriteBuffer(); 
    } 
} 

Como se puede ver, el QTextStreamPrivate tiene un buffer. Este buffer es del tipo QString. Entonces, ¿qué sucede cuando el buffer finalmente se imprime en el terminal? Para esto, tenemos que averiguar qué sucede cuando su declaración qDebug() finaliza y el búfer se pasa al manejador de mensajes, que, por defecto, imprime el búfer en el terminal. Esto está sucediendo en el destructor de la clase QDebug, que se define de la siguiente manera:

inline ~QDebug() { 
    if (!--stream->ref) { 
     if(stream->message_output) { 
     QT_TRY { 
      qt_message_output(stream->type, stream->buffer.toLocal8Bit().data()); 
     } QT_CATCH(std::bad_alloc&) { /* We're out of memory - give up. */ } 
     } 
     delete stream; 
    } 
} 

Así que aquí es la parte no binario de fallos. Qt toma el búfer textual, lo convierte en representación binaria "local de 8 bits" (hasta ahora, AFAIK aún deberíamos tener los datos binarios que queremos depurar).

Pero luego lo pasa al controlador de mensajes sin la especificación adicional de la longitud de los datos binarios. Como debería saber, es imposible determinar la longitud de una cuerda en C que también debería poder contener '\0' caracteres. (Por eso QString::fromAscii() en el código anterior necesita el parámetro de longitud adicional para binario de seguridad.)

Así que si usted quiere manejar las '\0' caracteres, incluso escribir su propio controlador de mensajes no va a resolver el problema, ya que no puede saber la longitud Triste pero cierto.

+0

No citaría la palabra "problema", realmente parece un error (como lo demuestra el cierre que falta "después de la cadena que qDebug normalmente agrega. –

+0

@fish También creo que truncar los datos en un' ' \ 0'' no es agradable. Por otro lado, supongo que las salidas de qDebug están hechas para datos textuales (al menos para QString y QByteArray). Se podría argumentar que en el caso de un QByteArray, este * no debería ser * se supone, pero también se puede argumentar que Qt podría no saber cómo quiere que se depuren los datos binarios. La salida de un carácter cero funciona pero no se puede leer (que es el propósito de qDebug()). Tal vez un .toHex() es la mejor solución para datos binarios en algunos casos. Así que supongo que Qt le deja a usted * cómo * dar salida a los datos. – leemes

+0

Aparte de eso, se puede argumentar que este es un comportamiento correcto, estoy bastante seguro fue involuntario, de lo contrario lo haría anexar el desaparecido ". –

Cuestiones relacionadas