简体   繁体   English

转换数据类型以添加​​到 QByteArray 以将原始数据写入文件

[英]Converting data types to add to QByteArray for writing raw data to file

I have some data types that I am trying to write to to a raw data file.我有一些数据类型试图写入原始数据文件。 I'm not using QDataStream because that writes some extra information about the data, like the length and order of data.我没有使用 QDataStream 因为它写了一些关于数据的额外信息,比如数据的长度和顺序。 I simply want a file that is only the bytes that I write, and will only be interpreted by someone who knows the correct order and size of the data types being written.我只想要一个只有我写的字节的文件,并且只能由知道正在写入的数据类型的正确顺序和大小的人来解释。

I am using QFile, with the write method qint64 QIODevice::write(const QByteArray &byteArray) .我正在使用 QFile,写方法qint64 QIODevice::write(const QByteArray &byteArray)

I have a few uint8_t, uint32_t and floats to write to the file.我有一些 uint8_t、uint32_t 和浮点数来写入文件。 How can I transform this data into a QByteArray with no extra bytes?如何将此数据转换为没有额外字节的 QByteArray?

Here is what I have so far:这是我到目前为止所拥有的:

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

A regular old style cast to char gives me an implicit conversion changes signedness error, so that wouldn't store the value correctly.常规的旧样式implicit conversion changes signednesschar给我一个implicit conversion changes signedness错误,因此不会正确存储值。

what is the proper way to copies these values into a QByteArray so I can write it to file?将这些值复制到 QByteArray 以便我可以将其写入文件的正确方法是什么?

Generally you want to serialize your data streams while keeping note of the endianness of the data.通常,您希望序列化数据流,同时注意数据的字节序。

uint8_t variables can be converted to bytes with a simple static_cast . uint8_t变量可以通过简单的static_cast转换为字节。 For larger integer types, you need to keep track of the endianness of the data, and push it byte by byte.对于较大的整数类型,您需要跟踪数据的字节序,并逐字节推送。

float data types are a little bit trickier. float数据类型有点棘手。 You first need to represent the bits of the float as an integral value ( uint32_t ), then serialize from there.您首先需要将浮点数的位表示为整数值 ( uint32_t ),然后从那里序列化。 An example can be shown below:一个例子可以显示如下:

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

A few things to keep in mind:需要牢记以下几点:

  1. The endianness of your data is important.数据的字节序很重要。 Not all systems have the same endianness so you need to be explicit in your documentation about which way the bytes are oriented.并非所有系统都具有相同的字节顺序,因此您需要在文档中明确说明字节的方向。

  2. Some people try to convert the bits of a float to a uint32_t by writing something like uint32_t rep = *reinterpret_cast<uint32_t*>(&source0);有些人试图通过编写类似uint32_t rep = *reinterpret_cast<uint32_t*>(&source0);东西将float的位转换为uint32_t uint32_t rep = *reinterpret_cast<uint32_t*>(&source0); . . Don't do this -- it is a violation of the Strict Aliasing Rule .不要这样做——这违反了严格别名规则

  3. It may be a good idea to serialize a version number as the first part of your file so that you can make future changes to the data format and have it be backwards-compatible.将版本号序列化为文件的第一部分可能是一个好主意,以便您可以在未来更改数据格式并使其向后兼容。

  4. A lot of this manual bit-packing can be written into template functions that will do it automatically.许多这种手动位打包可以写入模板函数中,这些函数会自动完成。 This is left as an exercise to the reader.这留给读者作为练习。

  5. If performance is important, you should figure out how large the data will be and reserve() the space in the byte array before pushing -- this will save the array from having to reallocate and grow over and over.如果性能很重要,您应该弄清楚数据有多大,并在推送之前reserve()字节数组中的空间——这将使数组免于重新分配和一遍又一遍地增长。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM