Как правильно хранить необработанные байтовые данные в XML и восстанавливать их? - PullRequest
0 голосов
/ 07 января 2020

Используя C ++ и Qt, мне нужно сохранить некоторые необработанные байтовые данные (массив без знака) в QDomElement (узел XML), а затем восстановить его позже, чтобы я мог сравнить его с записанными необработанными данными непосредственно в другой двоичный файл. Во время тестирования я заметил, что мое решение работает ~ 85% времени, но сравнение восстановленных данных и необработанных данных, считываемых из файла, иногда дает сбой. Приведенные ниже фрагменты кода иллюстрируют методы Qt, которые я сейчас использую. У меня очень мало знаний о различных кодировках символов и о том, что мне нужно искать в этом отношении, поэтому я предполагаю, что моя ошибка как-то связана с этим.

Хранение необработанных данных в 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 ) );

Восстановление данных из XML и сравнение с необработанными данными, считанными из двоичного файла (иногда происходит сбой memcmp ()):

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

Я ограничен Qt 4.8, поэтому пожалуйста, воздержитесь от любых решений Qt5-speci c, если возможно, спасибо!

Ответы [ 3 ]

1 голос
/ 08 января 2020

Вы заявляете, что байты являются случайными, поэтому они могут содержать 0 байтов. Значение байта 0 - это терминатор строки в стиле C. Эта строка в вашем коде инициализирует QByteArray из такой строки:

QByteArray dataByteArray( reinterpret_cast< char * >( rawData ) );

Решением также является передача длины rawData и использование этого конструктора .

0 голосов
/ 07 января 2020

Почему бы вам не использовать QDataStream , который может определять порядок байтов (важно при обмене данными между различными платформами) и управление версиями?

На странице документации Qt 4.8:

Поток данных тесно взаимодействует с QIODevice. QIODevice представляет собой носитель ввода / вывода, с которого можно считывать и записывать данные. Класс QFile является примером устройства ввода-вывода.

Пример (запись двоичных данных в поток):

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

Пример (чтение двоичных данных из потока):

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

Каждый элемент, записанный в поток, записывается в предопределенном двоичном формате, который варьируется в зависимости от типа элемента. Поддерживаемые типы Qt включают QBru sh, QColor, QDateTime, QFont, QPixmap, QString, QVariant и многие другие. Полный список всех типов Qt, поддерживающих потоковую передачу данных, см. Сериализация типов данных Qt .

Вы можете читать / записывать свои XML данные с помощью QDataStream и импортируйте их в структуру QDomDocument с помощью функции QDomDocument setContent() и toByteArray().

0 голосов
/ 07 января 2020

Вы хотите использовать XML раздел CDATA.

Посмотрите на QDomCDATASection

https://doc.qt.io/archives/qt-4.8/qdomcdatasection.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...