Converting data types to add to QByteArray for write raw data to file

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

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

将常规旧样式强制转换为 char 会给我一个 implicit conversion changes signedness 错误,因此无法正确存储该值。

将这些值复制到 QByteArray 以便我可以将其写入文件的正确方法是什么?


通常,您希望序列化数据流,同时注意数据的字节顺序。

uint8_t 变量可以通过简单的 static_cast 转换为字节。对于较大的整数类型,您需要跟踪数据的字节顺序,并逐字节推送。

float 数据类型有点棘手。您首先需要将浮点数的位表示为整数值 (uint32_t),然后从那里进行序列化。示例如下:

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

}
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。不要这样做——这违反了严格别名规则。

  • 将版本号序列化为文件的第一部分可能是个好主意,这样您以后可以对数据格式进行更改并使其向后兼容。

  • 很多这种手动位打包可以写入模板函数,自动完成。这留给读者作为练习。

  • 如果性能很重要,您应该在推送之前弄清楚数据的大小和字节数组中的空间 reserve() ——这将使数组不必重新分配和一遍又一遍地增长。


相关推荐

  • Spring部署设置openshift

    Springdeploymentsettingsopenshift我有一个问题让我抓狂了三天。我根据OpenShift帐户上的教程部署了spring-eap6-quickstart代码。我已配置调试选项,并且已将Eclipse工作区与OpehShift服务器同步-服务器上的一切工作正常,但在Eclipse中出现无法消除的错误。我有这个错误:cvc-complex-type.2.4.a:Invali…
    2025-04-161
  • 检查Java中正则表达式中模式的第n次出现

    CheckfornthoccurrenceofpatterninregularexpressioninJava本问题已经有最佳答案,请猛点这里访问。我想使用Java正则表达式检查输入字符串中特定模式的第n次出现。你能建议怎么做吗?这应该可以工作:MatchResultfindNthOccurance(intn,Patternp,CharSequencesrc){Matcherm=p.matcher…
    2025-04-161
  • 如何让 JTable 停留在已编辑的单元格上

    HowtohaveJTablestayingontheeditedcell如果有人编辑JTable的单元格内容并按Enter,则内容会被修改并且表格选择会移动到下一行。是否可以禁止JTable在单元格编辑后转到下一行?原因是我的程序使用ListSelectionListener在单元格选择上同步了其他一些小部件,并且我不想在编辑当前单元格后选择下一行。Enter的默认绑定是名为selectNext…
    2025-04-161
  • Weblogic 12c 部署

    Weblogic12cdeploy我正在尝试将我的应用程序从Tomcat迁移到Weblogic12.2.1.3.0。我能够毫无错误地部署应用程序,但我遇到了与持久性提供程序相关的运行时错误。这是堆栈跟踪:javax.validation.ValidationException:CalltoTraversableResolver.isReachable()threwanexceptionatorg.…
    2025-04-161
  • Resteasy Content-Type 默认值

    ResteasyContent-Typedefaults我正在使用Resteasy编写一个可以返回JSON和XML的应用程序,但可以选择默认为XML。这是我的方法:@GET@Path("/content")@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})publicStringcontentListRequestXm…
    2025-04-161
  • 代码不会停止运行,在 Java 中

    thecodedoesn'tstoprunning,inJava我正在用Java解决项目Euler中的问题10,即"Thesumoftheprimesbelow10is2+3+5+7=17.Findthesumofalltheprimesbelowtwomillion."我的代码是packageprojecteuler_1;importjava.math.BigInteger;importjava…
    2025-04-161
  • Out of memory java heap space

    Outofmemoryjavaheapspace我正在尝试将大量文件从服务器发送到多个客户端。当我尝试发送大小为700mb的文件时,它显示了"OutOfMemoryjavaheapspace"错误。我正在使用Netbeans7.1.2版本。我还在属性中尝试了VMoption。但仍然发生同样的错误。我认为阅读整个文件存在一些问题。下面的代码最多可用于300mb。请给我一些建议。提前致谢publicc…
    2025-04-161
  • Log4j 记录到共享日志文件

    Log4jLoggingtoaSharedLogFile有没有办法将log4j日志记录事件写入也被其他应用程序写入的日志文件。其他应用程序可以是非Java应用程序。有什么缺点?锁定问题?格式化?Log4j有一个SocketAppender,它将向服务发送事件,您可以自己实现或使用与Log4j捆绑的简单实现。它还支持syslogd和Windows事件日志,这对于尝试将日志输出与来自非Java应用程序…
    2025-04-161