Reputation: 191
Using C++ and Qt, I need to store some raw byte data (an unsigned char array) in a QDomElement (XML node), and then recover it later so that I can compare it to the raw data that is written directly to a different binary file. During testing, I noticed my solution works ~85% of the time, but comparing the recovered data and the raw data read from file seems to fail occasionally. The code snippets below illustrate the Qt methods I am currently using. I have very little knowledge of different character encodings and what I need to look out for in that regard, so I am assuming my mistake has something to do with that.
Storing the raw data in XML:
QDomElement myElement;
unsigned char rawData[ DATA_LEN ];
foo( rawData ); // upon return, rawData now contains the data I want to store in XML
QByteArray dataByteArray( reinterpret_cast< char * >( rawData ) );
QString dataStr( dataByteArray.toBase64() );
QByteArray excluded = " /():|+,.=[]_^{}";
myElement.setAttribute( "Data", QUrl::toPercentEncoding( dataStr, excluded ) );
Recovering the data from XML and comparing to raw data read from binary file (the memcmp() occasionally fails):
unsigned char recoveredData[ DATA_LEN ];
QString dataStr = QUrl::fromPercentEncoding( stringFromXmlNode.toUtf8() );
QByteArray dataByteArray = QByteArray::fromBase64( dataStr.toAscii() );
memcpy( recoveredData, reinterpret_cast< unsigned char * >( dataByteArray.data() ), DATA_LEN );
unsigned char dataFromFile[ DATA_LEN ];
fread( dataFromFile, 1, DATA_LEN, filePtr );
if( 0 != memcmp( dataFromFile, recoveredData, DATA_LEN ) )
{
return false;
}
I am restricted to Qt 4.8, so please refrain from any Qt5-specific solutions if possible, thanks!
Upvotes: 0
Views: 934
Reputation: 62848
You state the bytes are random, so they can contain 0 bytes. Byte value 0 is string terminator in C-style strings. This line in your code initializes QByteArray
from such string:
QByteArray dataByteArray( reinterpret_cast< char * >( rawData ) );
Solution is to also pass length of rawData
and use this constructor.
Upvotes: 1
Reputation: 2893
Why don't you use QDataStream, which can define the byte order (important if exchanging data across different platforms) and the versioning?
From the Qt 4.8 documentation page:
A data stream cooperates closely with a QIODevice. A QIODevice represents an input/output medium one can read data from and write data to. The QFile class is an example of an I/O device.
Example (write binary data to a stream):
QFile file("file.dat"); file.open(QIODevice::WriteOnly); QDataStream out(&file); // we will serialize the data into the file out << QString("the answer is"); // serialize a string out << (qint32)42; // serialize an integer
Example (read binary data from a stream):
QFile file("file.dat"); file.open(QIODevice::ReadOnly); QDataStream in(&file); // read the data serialized from the file QString str; qint32 a; in >> str >> a; // extract "the answer is" and 42
Each item written to the stream is written in a predefined binary format that varies depending on the item's type. Supported Qt types include QBrush, QColor, QDateTime, QFont, QPixmap, QString, QVariant and many others. For the complete list of all Qt types supporting data streaming see Serializing Qt Data Types.
You can read/write your XML Data with QDataStream and import them in the QDomDocument structure with the QDomDocument function setContent()
and toByteArray()
.
Upvotes: 0
Reputation: 89222
You want to use an XML CDATA section.
Look at QDomCDATASection
https://doc.qt.io/archives/qt-4.8/qdomcdatasection.html
Upvotes: 0