QByteArray中带有QDataStream的char *中的空字节

时间:2014-06-08 23:46:36

标签: c++ qt

我发现char*中的QByteArray有空字节。代码:

QByteArray arr;
QDataStream stream(&arr, QIODevice::WriteOnly);
stream << "hello";

查看调试器变量视图:

char* in QByteArray

我不明白为什么我在开头有三个空字节。我知道[3]字节是字符串长度。我能删除最后一个字节吗?我知道它是以空字符结尾的字符串,但对于我的应用程序,我必须有原始字节(在存储长度的初始化时有一个字节)。

对我来说更奇怪的是当我使用QString时:

QString str = "hello";
[rest of code same as above]
stream << str;

QString in QByteArray

它最后没有空,所以我想在每个char之前可能是null字节,通知下一个字节是char?

只有两个问题:

  1. 为什么这么多空字节?
  2. 我如何删除它,包括最后一个空字节?

1 个答案:

答案 0 :(得分:4)

  

我不明白为什么我在开头有三个空字节。

它是一个固定大小的uint32_t(4字节)标头。它是四个字节,因此它可以指定长度为(2 ^ 32-1)个字节的数据长度。如果它只是一个字节,那么它只能描述长达255个字节的字符串,因为它是可以放入单个字节的最大整数值。

  

我可以删除最后一个字节吗?我知道它是以空字符结尾的字符串,但对于我的   应用程序我必须有原始字节(在beggining时有一个字节   商店长度)。

当然,只要稍后解析数据数组的代码不依赖于尾随NUL字节的存在就能正常工作。

  

对我来说更奇怪的是,当我使用QString时,它不会在结尾处有空,所以我想在每个char之前可能是空字节通知下一个字节是char?

根据Qt serialization documentation page,QString被序列化为:

- If the string is null: 0xFFFFFFFF (quint32)
- Otherwise:  The string length in bytes (quint32) followed by the data in UTF-16.

如果您不喜欢这种格式,而不是直接序列化QString,您可以执行类似

的操作
stream << str.toUtf8();
相反,这样,QByteArray中的数据将采用更简单的格式(UTF-8)。

  

为什么这么多空字节?

当编码的长度值很小时,它们用于固定大小的头字段;或指示NUL终止的C字符串的结束。

  

我如何删除它,包括最后一个空字节?

你可以用你喜欢的格式添加字符串(没有NUL终结符但是有一个长度的header-byte),如下所示:

const char * hello = "hello";
char slen = strlen(hello);
stream.writeRawData(&slen, 1);
stream.writeRawData(hello, slen);

...但如果您有选择,我强烈建议您将NUL终结符字节保留在字符串的末尾,原因如下:

  1. 前一个长度字节会将字符串限制为255个字节长(或更短),这是一个不必要的限制,可能会在将来困扰您。

  2. 避免NUL终结符字节实际上并没有节省任何空间,因为你已经添加了一个字符串长度的字节来补偿。

  3. 如果NUL-terminator字节在那里,你可以简单地将指向字符串的第一个字节的指针直接传递给任何需要C风格字符串的代码,并且它可以立即使用该字符串(没有任何数据转换步骤)。如果您依赖于不同的约定,那么在将其传递给该代码之前,您最终必须复制整个字符串,这样才能将NUL字节附加到字符串的末尾,以便C字符串期望代码可以使用它。这将是CPU效率低下且容易出错的。