使用 QString 和 QByteArray 的 QDataStream 问题
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
我用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的size加6,这是为什么呢? sizeof(QString)
是 4。
通过检查 Qt Documentation for QDatastream,如何存储和检索字符串:
a char * string is written as a 32-bit integer equal to the length of
the string including the '[=10=]' byte, followed by all the characters of
the string including the '[=10=]' byte. When reading a char * string, 4
bytes are read to create the 32-bit length value, then that many
characters for the char * string including the '[=10=]' terminator are
read.
所以在你的情况下,字符串长度为 32 位 + "a" 为 1 字节 + \0 为 1 字节,总计为 6 个字节。
让我们来分析一下两种印象之间的区别:
"\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)
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.
即除了写入数据外,写入quint32
格式的文本长度(4字节),缓冲区长度等于sizeOf(QChar)
x length of the QString
.
考虑到其中我们可以更好地理解结果:
x00\x00\x00\x02 \x00""a
--------------- -------
numbers of bytes of buffer buffer
一般情况下可以使用以下公式计算存储数据的大小:
length stored data = 4 + 2 x length of string
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的size加6,这是为什么呢? sizeof(QString)
是 4。
通过检查 Qt Documentation for QDatastream,如何存储和检索字符串:
a char * string is written as a 32-bit integer equal to the length of the string including the '[=10=]' byte, followed by all the characters of the string including the '[=10=]' byte. When reading a char * string, 4 bytes are read to create the 32-bit length value, then that many characters for the char * string including the '[=10=]' terminator are read.
所以在你的情况下,字符串长度为 32 位 + "a" 为 1 字节 + \0 为 1 字节,总计为 6 个字节。
让我们来分析一下两种印象之间的区别:
"\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)
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.
即除了写入数据外,写入quint32
格式的文本长度(4字节),缓冲区长度等于sizeOf(QChar)
x length of the QString
.
考虑到其中我们可以更好地理解结果:
x00\x00\x00\x02 \x00""a
--------------- -------
numbers of bytes of buffer buffer
一般情况下可以使用以下公式计算存储数据的大小:
length stored data = 4 + 2 x length of string