c++qtqstringqbytearrayqdatastream

Issues with QDataStream using QString and QByteArray


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

I use QDataStream to write 3 number, ba.size() is 7, but I'm confused about this:

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

If a QString's size is 1, ba's size plus 6, why is that? sizeof(QString) is 4.


Solution

  • Let's analyze the difference between both impressions:

    "\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
    

    And for that, let's review the 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;
    }
    

    That method uses the writeBytes() method, and according to the docs:

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

    Writes the length specifier len and the buffer s to the stream and returns a reference to the stream.

    The len is serialized as a quint32, followed by len bytes from s. Note that the data is not encoded.

    That is, apart from writing the data, write the length of the text in quint32 format (4 bytes) and the length of the buffer is equal to sizeOf(QChar) x length of the QString.

    Taking into account in it we can understand the result better:

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

    In general you can use the following formula to calculate the size of the stored data:

    length stored data = 4 + 2 x length of string