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.
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. –
@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
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 ". –