C++ 将数据类型转换为添加到QByteArray以将原始数据写入文件
我有一些试图写入原始数据文件的数据类型。我没有使用QDataStream,因为它会写入一些关于数据的额外信息,比如数据的长度和顺序。我只是想要一个只有我写的字节的文件,并且只能由知道所写数据类型的正确顺序和大小的人来解释 我使用的是QFile,其写入方法是C++ 将数据类型转换为添加到QByteArray以将原始数据写入文件,c++,qt,file,serialization,memcpy,C++,Qt,File,Serialization,Memcpy,我有一些试图写入原始数据文件的数据类型。我没有使用QDataStream,因为它会写入一些关于数据的额外信息,比如数据的长度和顺序。我只是想要一个只有我写的字节的文件,并且只能由知道所写数据类型的正确顺序和大小的人来解释 我使用的是QFile,其写入方法是qint64 QIODevice::write(constqbytearray&byteArray) 我有一些uint8\u t、uint32\u t和float要写入文件。如何将此数据转换为QByteArray,而无需额外的字节 以下是我到目
qint64 QIODevice::write(constqbytearray&byteArray)
我有一些uint8\u t、uint32\u t和float要写入文件。如何将此数据转换为QByteArray,而无需额外的字节
以下是我到目前为止的情况:
void FileWriter::writeData(uint8_t status, uint8_t channel, uint32_t ticks, float source0, float source1){
QByteArray dataToWrite;
//some code to add the paramters to the dataToWrite array
this->file.write(dataToWrite);
}
对char
进行常规旧式转换时,会出现隐式转换更改签名的错误,因此无法正确存储值
将这些值复制到QByteArray以便将其写入文件的正确方法是什么?通常,您希望序列化数据流,同时注意数据的结尾
uint8\u t
变量可以通过简单的static\u cast
转换为字节。对于较大的整数类型,您需要跟踪数据的endianness,并逐字节推送数据
float
数据类型有点棘手。首先需要将浮点的位表示为整数值(uint32\u t
),然后从那里序列化。示例如下所示:
QByteArray data;
//serialize a uint8_t
data.push_back(static_cast<char>(status));
//serialize a uint32_t, little-endian
data.push_back(static_cast<char>((ticks) & 0xFF); //lowest-order byte
data.push_back(static_cast<char>((ticks >> 8) & 0xFF));
data.push_back(static_cast<char>((ticks >> 16) & 0xFF));
data.push_back(static_cast<char>((ticks >> 24) & 0xFF)); //highest-order byte
//serialize a float, by first representing the bits as a uint32_t:
static_assert(sizeof(float) == sizeof(uint32_t), "Floats should be 4 bytes");
uint32_t rep;
std::memcpy(&rep, &source0, sizeof(float)); //using memcpy here so that we don't violate strict aliasing.
data.push_back(static_cast<char>((rep) & 0xFF);
data.push_back(static_cast<char>((rep >> 8) & 0xFF));
data.push_back(static_cast<char>((rep >> 16) & 0xFF));
data.push_back(static_cast<char>((rep >> 24) & 0xFF));
this->file.write(data);
QByteArray数据;
//序列化uint8\t
数据。推回(静态施法(状态));
//序列化uint32_t,小端点
data.push_back(static_cast((ticks)&0xFF);//最低顺序字节
数据。推回(静态转换((滴答声>>8)和0xFF));
数据。推回(静态转换((滴答声>>16)和0xFF));
data.push_back(静态_cast((ticks>>24)&0xFF));//最高顺序字节
//通过首先将位表示为uint32\t来序列化浮点:
静态断言(sizeof(float)=sizeof(uint32_t),“float应该是4个字节”);
uint32_t代表;
std::memcpy(&rep,&source0,sizeof(float));//在这里使用memcpy,这样我们就不会违反严格的别名。
数据。推回(静态转换((rep)和0xFF);
数据。推回(静态转换((rep>>8)和0xFF));
数据。推回(静态转换((rep>>16)和0xFF));
数据。推回(静态转换((rep>>24)和0xFF));
此->文件.写入(数据);
需要记住的几件事:
数据的尾数很重要。并非所有系统都具有相同的尾数,因此您需要在文档中明确说明字节的方向
有些人试图通过编写类似于uint32\u t rep=*reinterpret\u cast(&source0);
的内容,将float
的位转换为uint32\u t
最好将版本号序列化为文件的第一部分,以便将来可以对数据格式进行更改并使其向后兼容
很多这种手动位打包都可以写入模板函数,这些函数将自动完成。这将留给读者作为练习
如果性能很重要,那么在推送之前,您应该计算出数据的大小以及字节数组中的空间大小,这样可以避免数组不得不重新分配和不断增长
通常,您希望序列化数据流,同时注意数据的结尾
uint8\u t
变量可以通过简单的static\u cast
转换为字节。对于较大的整数类型,您需要跟踪数据的尾数,并逐字节推送数据
float
数据类型有点复杂。首先需要将浮点的位表示为整数值(uint32\u t
),然后从那里序列化。下面可以显示一个示例:
QByteArray data;
//serialize a uint8_t
data.push_back(static_cast<char>(status));
//serialize a uint32_t, little-endian
data.push_back(static_cast<char>((ticks) & 0xFF); //lowest-order byte
data.push_back(static_cast<char>((ticks >> 8) & 0xFF));
data.push_back(static_cast<char>((ticks >> 16) & 0xFF));
data.push_back(static_cast<char>((ticks >> 24) & 0xFF)); //highest-order byte
//serialize a float, by first representing the bits as a uint32_t:
static_assert(sizeof(float) == sizeof(uint32_t), "Floats should be 4 bytes");
uint32_t rep;
std::memcpy(&rep, &source0, sizeof(float)); //using memcpy here so that we don't violate strict aliasing.
data.push_back(static_cast<char>((rep) & 0xFF);
data.push_back(static_cast<char>((rep >> 8) & 0xFF));
data.push_back(static_cast<char>((rep >> 16) & 0xFF));
data.push_back(static_cast<char>((rep >> 24) & 0xFF));
this->file.write(data);
QByteArray数据;
//序列化uint8\t
数据。推回(静态施法(状态));
//序列化uint32_t,小端点
data.push_back(static_cast((ticks)&0xFF);//最低顺序字节
数据。推回(静态转换((滴答声>>8)和0xFF));
数据。推回(静态转换((滴答声>>16)和0xFF));
data.push_back(静态_cast((ticks>>24)&0xFF));//最高顺序字节
//通过首先将位表示为uint32\t来序列化浮点:
静态断言(sizeof(float)=sizeof(uint32_t),“float应该是4个字节”);
uint32_t代表;
std::memcpy(&rep,&source0,sizeof(float));//在这里使用memcpy,这样我们就不会违反严格的别名。
数据。推回(静态转换((rep)和0xFF);
数据。推回(静态转换((rep>>8)和0xFF));
数据。推回(静态转换((rep>>16)和0xFF));
数据。推回(静态转换((rep>>24)和0xFF));
此->文件.写入(数据);
需要记住的几件事:
数据的尾数很重要。并非所有系统都具有相同的尾数,因此您需要在文档中明确说明字节的方向
有些人试图通过编写类似于uint32\u t rep=*reinterpret\u cast(&source0);
的内容,将float
的位转换为uint32\u t
最好将版本号序列化为文件的第一部分,以便将来可以对数据格式进行更改并使其向后兼容
很多这种手动位打包都可以写入模板函数,这些函数将自动完成。这将留给读者作为练习
如果性能很重要,那么在推送之前,您应该计算出数据的大小以及字节数组中的空间大小,这样可以避免数组不得不重新分配和不断增长
谢谢。到目前为止,应用程序将只在一个平台上运行,因此endianness现在不是非常重要。这是perfec