使用 QString 和 QByteArray 的 QDataStream 问题

Issues with QDataStream using QString and QByteArray

本文关键字:QDataStream 问题 QByteArray QString 使用      更新时间:2023-10-16
QByteArray ba;
QDataStream ds(&ba,QIODevice::WriteOnly);
ds<<quint8(1)<<quint16(2)<<quint32(3);  //1+2+4
qDebug()<<"size:"<<ba.size();   // 7

我用QDataStream写3个数字,ba.size((是7,但我对此感到困惑:

QByteArray ba;
QDataStream ds(&ba,QIODevice::WriteOnly);
QString s="a";
ds<<quint8(1)<<quint16(2)<<quint32(3)<<s;  //1+2+4+a
qDebug()<<"size:"<<ba.size();   // 13

如果QString的size是1,ba的大小加6,为什么会这样?sizeof(QString)是 4。

让我们分析一下这两种展示之间的区别:

"x01x00x02x00x00x00x03"
"x01x00x02x00x00x00x03x00x00x00x02x00""a"
-----------------------------------------------------
x00x00x00x02x00""a

为此,让我们回顾一下源代码:

QDataStream &operator<<(QDataStream &out, const QString &str)
{
if (out.version() == 1) {
out << str.toLatin1();
} else {
if (!str.isNull() || out.version() < 3) {
if ((out.byteOrder() == QDataStream::BigEndian) == (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
out.writeBytes(reinterpret_cast<const char *>(str.unicode()), sizeof(QChar) * str.length());
} else {
QVarLengthArray<ushort> buffer(str.length());
const ushort *data = reinterpret_cast<const ushort *>(str.constData());
for (int i = 0; i < str.length(); i++) {
buffer[i] = qbswap(*data);
++data;
}
out.writeBytes(reinterpret_cast<const char *>(buffer.data()), sizeof(ushort) * buffer.size());
}
} else {
// write null marker
out << (quint32)0xffffffff;
}
}
return out;
}

该方法使用writeBytes()方法, 根据文档:

QDataStream &QDataStream::writeBytes(const char *s, uint len(

长度说明符 len和缓冲区写入流,并且返回对流的引用。

len 被序列化为 quint32,后跟来自 s 的 len 字节。 注意 数据未编码。

也就是说,除了写入数据外,以quint32格式(4 字节(写入文本的长度,缓冲区的长度等于sizeOf(QChar)xlength of the QString

考虑到这一点,我们可以更好地理解结果:

x00x00x00x02          x00""a
---------------          -------
numbers of bytes of buffer    buffer

通常,您可以使用以下公式来计算存储数据的大小:

length stored data = 4 + 2 x length of string

通过检查QDatastream的Qt文档,如何存储和检索字符串:

字符 * 字符串写为 32 位整数,长度等于 包含"\0"字节的字符串,后跟 包含"\0"字节的字符串。读取字符 * 字符串时,4 读取字节以创建 32 位长度值,然后很多 字符 * 字符串的字符(包括"\0"终止符(是 读。

因此,在您的情况下,字符串长度为 32 位 + "a"为 1 字节 + \0 为 1 个字节,总和为 6 个字节。