转换数据类型以添加到 QByteArray 以将原始数据写入文件
Converting data types to add to QByteArray for writing raw data to file
我有一些数据类型正在尝试写入原始数据文件。我没有使用 QDataStream,因为它会写入一些关于数据的额外信息,比如数据的长度和顺序。我只想要一个只有我写入的字节的文件,并且只能由知道所写入数据类型的正确顺序和大小的人解释。
我正在使用 QFile,写入方法 qint64 QIODevice::write(const QByteArray &byteArray)
。
我有一些uint8_t、uint32_t和浮动要写入文件。如何将此数据转换为没有额外字节的 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
的常规旧样式给我一个 implicit conversion changes signedness
错误,因此无法正确存储值。
将这些值复制到 QByteArray 以便我可以将其写入文件的正确方法是什么?
通常,您希望序列化数据流,同时注意数据的字节顺序。
uint8_t
变量可以通过简单的 static_cast
转换为字节。对于较大的整数类型,您需要跟踪数据的字节顺序,并逐字节推送。
float
数据类型有点棘手。您首先需要将浮点数的位表示为整数值 (uint32_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);
需要牢记的几点:
数据的字节顺序很重要。并非所有系统都具有相同的字节顺序,因此您需要在文档中明确说明字节的定向方式。
有些人试图通过编写类似 uint32_t rep = *reinterpret_cast<uint32_t*>(&source0);
的代码将 float
的位转换为 uint32_t
。不要这样做——这违反了 Strict Aliasing Rule。
将版本号序列化为文件的第一部分可能是个好主意,这样您就可以在将来更改数据格式并使其向后兼容。
很多这种手动位打包都可以写入模板函数中,自动完成。这是留给 reader.
的练习
如果性能很重要,你应该在推送之前计算出数据的大小和reserve()
字节数组中的space——这将节省数组从不得不重新分配和一遍又一遍地成长。
我有一些数据类型正在尝试写入原始数据文件。我没有使用 QDataStream,因为它会写入一些关于数据的额外信息,比如数据的长度和顺序。我只想要一个只有我写入的字节的文件,并且只能由知道所写入数据类型的正确顺序和大小的人解释。
我正在使用 QFile,写入方法 qint64 QIODevice::write(const QByteArray &byteArray)
。
我有一些uint8_t、uint32_t和浮动要写入文件。如何将此数据转换为没有额外字节的 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
的常规旧样式给我一个 implicit conversion changes signedness
错误,因此无法正确存储值。
将这些值复制到 QByteArray 以便我可以将其写入文件的正确方法是什么?
通常,您希望序列化数据流,同时注意数据的字节顺序。
uint8_t
变量可以通过简单的 static_cast
转换为字节。对于较大的整数类型,您需要跟踪数据的字节顺序,并逐字节推送。
float
数据类型有点棘手。您首先需要将浮点数的位表示为整数值 (uint32_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);
需要牢记的几点:
数据的字节顺序很重要。并非所有系统都具有相同的字节顺序,因此您需要在文档中明确说明字节的定向方式。
有些人试图通过编写类似
uint32_t rep = *reinterpret_cast<uint32_t*>(&source0);
的代码将float
的位转换为uint32_t
。不要这样做——这违反了 Strict Aliasing Rule。将版本号序列化为文件的第一部分可能是个好主意,这样您就可以在将来更改数据格式并使其向后兼容。
很多这种手动位打包都可以写入模板函数中,自动完成。这是留给 reader.
的练习
如果性能很重要,你应该在推送之前计算出数据的大小和
reserve()
字节数组中的space——这将节省数组从不得不重新分配和一遍又一遍地成长。