【问题标题】:Issues with QDataStream using QString and QByteArray使用 QString 和 QByteArray 的 QDataStream 问题
【发布时间】:2023-03-08 17:31:01
【问题描述】:
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。

【问题讨论】:

    标签: c++ qt qstring qbytearray qdatastream


    【解决方案1】:

    我们来分析一下这两种印象的区别:

    "\x01\x00\x02\x00\x00\x00\x03"
    "\x01\x00\x02\x00\x00\x00\x03\x00\x00\x00\x02\x00""a"
    -----------------------------------------------------
                                  x00\x00\x00\x02\x00""a
    

    为此,让我们回顾一下source code

    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() 方法, 并根据docs:

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

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

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

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

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

          x00\x00\x00\x02          \x00""a
          ---------------          -------
      numbers of bytes of buffer    buffer
    

    一般可以使用以下公式来计算存储数据的大小:

    length stored data = 4 + 2 x length of string
    

    【讨论】:

    • 谢谢,真的很有帮助,令人印象深刻
    【解决方案2】:

    通过检查Qt Documentation for QDatastream,字符串是如何存储和检索的:

    一个 char * 字符串被写成一个 32 位整数,等于 包含 '\0' 字节的字符串,后跟的所有字符 包含 '\0' 字节的字符串。读取 char * 字符串时,4 读取字节以创建 32 位长度值,那么很多 包括 '\0' 终止符的 char * 字符串的字符是 阅读。

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

    【讨论】:

      猜你喜欢
      • 2017-12-12
      • 2020-07-10
      • 1970-01-01
      • 2012-12-17
      • 2020-08-15
      • 2014-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多