QCborStreamWriter 类

QCborStreamWriter 类是一个在单向流上操作的基本 CBOR 编码器。 更多...

头文件 #include <QCborStreamWriter>
CMakefind_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)
qmakeQT += core

注意: 此类中的所有函数都是 可重入的

公开函数

QCborStreamWriter(QIODevice *device)
QCborStreamWriter(QByteArray *data)
~QCborStreamWriter()
voidappend(quint64 u)
voidappend(qint64 i)
voidappend(QCborNegativeInteger n)
voidappend(const QByteArray &ba)
voidappend(QLatin1StringView str)
voidappend(QStringView str)
voidappend(QCborTag tag)
voidappend(QCborKnownTags tag)
voidappend(QCborSimpleType st)
voidappend(std::nullptr_t)
voidappend(qfloat16 f)
voidappend(float f)
voidappend(double d)
voidappend(bool b)
voidappend(const char *str, qsizetype size = -1)
voidappendByteString(const char *data, qsizetype len)
voidappendNull()
voidappendTextString(const char *utf8, qsizetype len)
voidappendUndefined()
QIODevice *device() const
boolendArray()
boolendMap()
voidsetDevice(QIODevice *device)
voidstartArray()
voidstartArray(quint64 count)
voidstartMap()
voidstartMap(quint64 count)

详细说明

此类可用于快速将CBOR内容流编码为QByteArrayQIODevice。CBOR是简洁的二进制对象表示形式,是一种紧凑的二进制数据编码形式,与JSON兼容。它由IETF约束RESTful环境(CoRE)工作组创建,已将其用于许多新的RFC中。它旨在与CoAP协议一起使用。

QCborStreamWriter提供了一个类似StAX的API,类似于QXmlStreamWriter。它相当底层,需要一些CBOR编码知识。对于更简单的API,请参阅QCborValue和特别是编码函数QCborValue::toCbor()。

QCborStreamWriter的典型用法是在目标QByteArrayQIODevice上创建对象,然后调用append()重载函数中的一个,带有要编码的期望类型。为了创建数组和映射,QCborStreamWriter提供了startArray()和startMap()重载函数,必须通过相应的endArray()和endMap()函数来结束。

以下示例编码了等效于以下JSON内容:

{ "label": "journald", "autoDetect": false, "condition": "libs.journald", "output": [ "privateFeature" ] }

   writer.startMap(4);    // 4 elements in the map

   writer.append("label"_L1);
   writer.append("journald"_L1);

   writer.append("autoDetect"_L1);
   writer.append(false);

   writer.append("condition"_L1);
   writer.append("libs.journald"_L1);

   writer.append("output"_L1);
   writer.startArray(1);
   writer.append("privateFeature"_L1);
   writer.endArray();

   writer.endMap();

CBOR支持

QCborStreamWriter支持所需创建规范和严格流的所有CBOR功能。它实现了RFC 7049中规定的几乎所有功能。

以下表列出了QCborStreamWriter支持的CBOR功能。

特征支持
无符号数是(全范围)
负数是(全范围)
字节字符串
文本字符串
分块字符串不是
标签是(任意)
布尔值
未定义
任意简单值
半精度浮点数(16位)
单精度浮点数(32位)
双精度浮点数(64位)
无穷大和NaN浮点数
确定长度的数组和映射
不确定长度的数组和映射
除字符串和整数以外的映射键类型是(任意)

规范CBOR编码

规范CBOR编码由RFC 7049的第3.9节定义。规范编码对Qt的CBOR解码功能不是必需的,但对于某些协议可能是必需的。特别是需要能够相同地复制相同流的协议可能需要此功能。

要被认为是“规范”的CBOR流必须满足以下要求:

  • 整数必须尽可能小。QCborStreamWriter始终这样做(不需要用户操作,并且不可能写入过长整数)。
  • 数组和映射的长度必须尽可能短。如上所述,QCborStreamWriter会自动这样做。
  • 数组、映射和字符串必须使用显式长度。QCborStreamWriter始终为字符串这样做;对于数组和映射,请确保使用具有显式长度的重载调用startArray()和startMap()。
  • 每个映射中的键必须按升序排序。QCborStreamWriter在这个方面没有提供帮助:开发者必须确保在调用映射对的append()之前。
  • 浮点值应尽可能小。QCborStreamWriter不会转换浮点值;开发者必须在调用append()之前执行此检查(请参阅那些函数的示例)。

严格CBOR模式

严格模式由RFC 7049的3.10节定义。至于上面的规范编码,QCborStreamWriter使得创建严格CBOR流成为可能,但它不要求这么做或验证输出是否是这样的。

  • 映射中的键必须是唯一的。QCborStreamWriter不对映射键进行验证。
  • 标签可能需要与其指定的正确类型配对。QCborStreamWriter不对标签的使用进行验证。
  • 文本字符串必须是正确编码的UTF-8。QCborStreamWriter总是使用正确的UTF-8写入使用append()添加的字符串,但对于使用appendTextString()添加的字符串则不进行验证。

无效CBOR流

也可能误用QCborStreamWriter生成无效的CBOR流,该流将无法被接收器解码。以下操作会产生无效流

  • 添加一个标签而没有添加相应的带标签值(QCborStreamWriter不产生诊断信息)。
  • 向具有显式长度(endMap()和endArray()将返回false,QCborStreamWriter将使用qWarning()记录日志)的数组或映射中添加太多或太少的项目。

{解析和显示CBOR数据}、{序列化转换器}、{保存和加载游戏}

另请参阅QCborStreamReaderQCborValueQXmlStreamWriter

成员函数文档

[显式]QCborStreamWriter::QCborStreamWriter(QIODevice *device)

创建一个将流写入device的QCborStreamWriter对象。在第一次append()调用之前必须打开设备。此构造函数可以与从QIODevice派生的任何类一起使用,例如QFileQProcessQTcpSocket

QCborStreamWriter没有缓冲,因此每次append()调用都将导致对设备write()方法的一次或多次调用。

以下示例将一个空映射写入文件

   QFile f("output", QIODevice::WriteOnly);
   QCborStreamWriter writer(&f);
   writer.startMap(0);
   writer.endMap();

QCborStreamWriter不拥有device

另请参阅device()和setDevice

[显式]QCborStreamWriter::QCborStreamWriter(QByteArray *data)

创建一个将流附加到data的QCborStreamWriter对象。所有流都立即写入到字节数组中,无需冲洗任何缓冲区。

以下示例将一个数字写入字节数组,然后返回它。

   QByteArray encodedNumber(qint64 value)
   {
       QByteArray ba;
       QCborStreamWriter writer(&ba);
       writer.append(value);
       return ba;
   }

QCborStreamWriter不拥有data

[无异常]QCborStreamWriter::~QCborStreamWriter()

销毁此QCborStreamWriter对象并释放任何关联的资源。

QCborStreamWriter在销毁对象之前不检查是否已将所有必需的项目写入流。这是程序员的职责来确保这一点。

void QCborStreamWriter::append(quint64 u)

这是一个重载的函数。

将64位无符号整数 u 添加到CBOR流中,创建一个CBOR无符号整数值。在以下示例中,我们将写入0、232UINT64_MAX的值。

   writer.append(0U);
   writer.append(Q_UINT64_C(4294967296));
   writer.append(std::numeric_limits<quint64>::max());

参见 QCborStreamReader::isUnsignedInteger() 和 QCborStreamReader::toUnsignedInteger

void QCborStreamWriter::append(qint64 i)

这是一个重载的函数。

将64位有符号整数 i 添加到CBOR流中。这将根据参数的符号创建CBOR无符号整数或CBOR负整数值。在以下示例中,我们将编写0、-1、232INT64_MAX的值。

   writer.append(0);
   writer.append(-1);
   writer.append(Q_INT64_C(4294967296));
   writer.append(std::numeric_limits<qint64>::max());

参见 QCborStreamReader::isInteger() 和 QCborStreamReader::toInteger

void QCborStreamWriter::append(QCborNegativeInteger n)

这是一个重载的函数。

将64位负值 n 添加到CBOR流中。QCborNegativeInteger是一个64位枚举,用于存储我们希望写入的负数的绝对值。如果n为零,所写入的值将相当于264(即-18,446,744,073,709,551,616)。

以下示例中将写入-1、-232和INT64_MIN的值。

   writer.append(QCborNegativeInteger(1));
   writer.append(QCborNegativeInteger(Q_INT64_C(4294967296)));
   writer.append(QCborNegativeInteger(-quint64(std::numeric_limits<qint64>::min())));

注意这个函数如何用于编码无法适应标准计算机64位有符号整数的数字,如qint64。也就是说,如果n大于std::numeric_limits::max()或为0,这将表示一个小于std::numeric_limits::min()的负数。

参见 QCborStreamReader::isNegativeInteger() 和 QCborStreamReader::toNegativeInteger

void QCborStreamWriter::append(const QByteArray &ba)

这是一个重载的函数。

将字节数组ba添加到流中,创建一个CBOR字节字符串值。QCborStreamWriter将尝试一次写入整个字符串。

以下示例将加载并将文件的全部内容追加到流中。

   void writeFile(QCborStreamWriter &writer, const QString &fileName)
   {
       QFile f(fileName);
       if (f.open(QIODevice::ReadOnly))
           writer.append(f.readAll());
   }

如示例所示,与JSON不同,CBOR不需要对二进制内容进行转义。

参见 appendByteString()、QCborStreamReader::isByteArray() 和 QCborStreamReader::readByteArray

void QCborStreamWriter::append(QLatin1StringView str)

这是一个重载的函数。

str的Latin-1字符串视图添加到流中,创建一个CBOR文本字符串值。QCborStreamWriter将尝试一次写入整个字符串。

以下示例将一个简单的Latin-1字符串字面值追加到流中。

   writer.append("Hello, World"_L1);

性能注意事项:CBOR要求所有文本字符串都使用UTF-8编码,因此此函数将遍历字符串中的字符以确定内容是否是US-ASCII。如果发现字符串包含US-ASCII之外的字符,则将分配内存并将其转换为UTF-8。如果此检查是不必要的,请使用appendTextString()代替。

参见 QCborStreamReader::isString() 和 QCborStreamReader::readString

void QCborStreamWriter::append(QStringView str)

这是一个重载的函数。

将文本字符串 str 添加到流中,创建一个 CBOR 文本字符串值。 QCborStreamWriter 尝试一次性写入整个字符串。

以下示例将一个任意的 QString 写入流中

   void writeString(QCborStreamWriter &writer, const QString &str)
   {
       writer.append(str);
   }

参见 QCborStreamReader::isString() 和 QCborStreamReader::readString

void QCborStreamWriter::append(QCborTag tag)

这是一个重载的函数。

将 CBOR 标签 tag 添加到流中,创建一个 CBOR 标签值。所有标签都必须跟在其定义意义的相关类型之后。

在以下示例中,我们将 CBOR 标签 36(正则表达式)和一个 QRegularExpression 的模式追加到流中

   void writeRxPattern(QCborStreamWriter &writer, const QRegularExpression &rx)
   {
       writer.append(QCborTag(36));
       writer.append(rx.pattern());
   }

另请参阅QCborStreamReader::isTag() 和 QCborStreamReader::toTag

void QCborStreamWriter::append(QCborKnownTags tag)

这是一个重载的函数。

将 CBOR 标签 tag 添加到流中,创建一个 CBOR 标签值。所有标签都必须跟在其定义意义的相关类型之后。

在以下示例中,我们将 CBOR 标签 1(Unix time_t)和一个代表当前时间的整数值添加到流中,该整数值是通过 time() 函数获得的

   void writeCurrentTime(QCborStreamWriter &writer)
   {
       writer.append(QCborKnownTags::UnixTime_t);
       writer.append(time(nullptr));
   }

另请参阅QCborStreamReader::isTag() 和 QCborStreamReader::toTag

void QCborStreamWriter::append(QCborSimpleType st)

这是一个重载的函数。

将 CBOR 简单类型 st 添加到流中,创建一个 CBOR 简单类型值。在以下示例中,我们写入 Null 类型的简单类型以及 Qt 没有支持的类型 32。

  writer.append(QCborSimpleType::Null);
  writer.append(QCborSimpleType(32));

注意:使用没有规定的简单类型可能会导致远程接收方的验证错误。此外,简单类型值 24 到 31(包括)是保留的,并且不能使用。

另请参阅QCborStreamReader::isSimpleType() 和 QCborStreamReader::toSimpleType

void QCborStreamWriter::append(std::nullptr_t)

这是一个重载的函数。

将 CBOR 空值添加到流中。此函数与以下(实现方式也相同):忽略参数。

   writer.append(QCborSimpleType::Null);

另请参阅appendNull(),append(QCborSimpleType) 和 QCborStreamReader::isNull

void QCborStreamWriter::append(qfloat16 f)

这是一个重载的函数。

将浮点数 f 添加到流中,创建一个 CBOR 16 位半精度浮点值。以下代码可以用以下方式使用,将 C++ float 转换为 qfloat16(如果不会丢失精度)并追加,或者直接追加 float

   void writeFloat(QCborStreamWriter &writer, float f)
   {
       qfloat16 f16 = f;
       if (qIsNaN(f) || f16 == f)
           writer.append(f16);
       else
           writer.append(f);
   }

另请参阅QCborStreamReader::isFloat16() 和 QCborStreamReader::toFloat16

void QCborStreamWriter::append(float f)

这是一个重载的函数。

将浮点数 f 添加到流中,创建一个 CBOR 32 位单精度浮点值。以下代码可用以下方式使用,将 C++ double 转换为 float(如果不会丢失精度)并追加,或者直接追加 double

   void writeFloat(QCborStreamWriter &writer, double d)
   {
       float f = d;
       if (qIsNaN(d) || d == f)
           writer.append(f);
       else
           writer.append(d);
   }

另请参阅QCborStreamReader::isFloat() 和 QCborStreamReader::toFloat

void QCborStreamWriter::append(double d)

这是一个重载的函数。

将浮点数 d 添加到流中,创建一个 CBOR 64 位双精度浮点值。 QCborStreamWriter 总是将数字原样添加,不检查数字是否为 NaN 的规范形式、无穷大、是否为非规格化数,或者是否可以用更短格式来表示。

以下代码执行了所有这些检查,除了非规格化数,这通常由系统 FPU 或浮点数模拟直接考虑。

   void writeDouble(QCborStreamWriter &writer, double d)
   {
       float f;
       if (qIsNaN(d)) {
           writer.append(qfloat16(qQNaN()));
       } else if (qIsInf(d)) {
           writer.append(d < 0 ? -qInf() : qInf());
       } else if ((f = d) == d) {
           qfloat16 f16 = f;
           if (f16 == f)
               writer.append(f16);
           else
               writer.append(f);
       } else {
           writer.append(d);
       }
   }

确定一个双精度浮点数是否可以无损地转换为整数是留给读者练习的内容。

另请参阅QCborStreamReader::isDouble() 和 QCborStreamReader::toDouble

void QCborStreamWriter::append(bool b)

这是一个重载的函数。

将布尔值 b 添加到流中,创建一个 CBOR False 值或 CBOR True 值。此函数与(并以)appendNull()、appendUndefined()、QCborStreamReader::isBool() 和 QCborStreamReader::toBool 相当。

   writer.append(b ? QCborSimpleType::True : QCborSimpleType::False);

另请参阅appendNull()、appendUndefined()、QCborStreamReader::isBool() 和 QCborStreamReader::toBool

void QCborStreamWriter::append(const char *str, qsizetype size = -1)

这是一个重载的函数。

str 开始添加 size 字节的文本到流中,创建一个 CBOR 文本字符串值。 QCborStreamWriter 将尝试一次性写入整个字符串。如果 size 为 -1,此函数将写入 strlen(\a str) 字节。

指向 str 的字符串应正确编码 UTF-8。 QCborStreamWriter 不进行验证以确认这一点。

QLatin1StringViewappend 重载不同,此函数不受 2 GB 的限制。但是,请注意, neither QCborStreamReader nor QCborValue 支持 2 GB 以上的文本字符串的 CBOR 流读取。

另请参阅append(QLatin1StringView)、append(QStringView)、QCborStreamReader::isString() 和 QCborStreamReader::readString

void QCborStreamWriter::appendByteString(const char *data, qsizetype len)

data 开始添加 len 字节数据到流中,创建一个 CBOR 字节字符串值。 QCborStreamWriter 将尝试一次性写入整个字符串。

QByteArrayappend 重载不同,此函数不受ByteArray 大小限制。但是,请注意, neither QCborStreamReader::readByteArray() nor QCborValue 支持 2 GB以上的字节序列的CBOR流读取。

另请参阅append()、appendTextString()、QCborStreamReader::isByteArray() 和 QCborStreamReader::readByteArray

void QCborStreamWriter::appendNull()

将 CBOR Null 值附加到流中。此函数等价于(并以相同方式实现为)

   writer.append(QCborSimpleType::Null);

另请参阅 append(std::nullptr_t), append(QCborSimpleType), 和 QCborStreamReader::isNull

void QCborStreamWriter::appendTextString(const char *utf8, qsizetype len)

将从 utf8 开始的 len 字节文本附加到流中,创建一个 CBOR 文本字符串值。.QCborStreamWriter 将尝试一次性写入整个字符串。

utf8 指向的字符串应正确使用 UTF-8 编码。.QCborStreamWriter 不会验证这一点。

QLatin1StringView 重载的 append 不同,此函数不限于 2 GB。但是请注意, neither QCborStreamReader::readString() nor QCborValue 支持 2 GB 以上文本字符串的 CBOR 流读取。

另请参阅append(QLatin1StringView)、append(QStringView)、QCborStreamReader::isString() 和 QCborStreamReader::readString

void QCborStreamWriter::appendUndefined()

将 CBOR Undefined 值附加到流中。此函数等价于(并以相同方式实现为)

   writer.append(QCborSimpleType::Undefined);

另请参阅 append(QCborSimpleType) 和 QCborStreamReader::isUndefined

QIODevice *QCborStreamWriter::device() const

返回此 QCborStreamWriter 对象正在写入的 QIODevice。此设备必须先前已通过构造函数或通过 setDevice() 设置。

如果此对象是通过写入到 QByteArray 创建的,则此函数将返回 QBuffer 的内部实例,该实例由 QCborStreamWriter 所拥有。

另请参阅 setDevice

bool QCborStreamWriter::endArray()

通过 startArray() 的任一重载启动数组并返回 true,如果已向数组添加正确的元素数量。对于使用的每个 startArray() 必须调用此函数。

返回值为 false 表明应用程序中存在错误,并且在此流中发生不可恢复的错误。.QCborStreamWriter 还会在发生这种情况时使用 qWarning() 写入警告。

当当前容器不是数组时调用此函数也是错误,尽管 QCborStreamWriter 目前无法检测此条件。

另请参阅 startArray(), startArray(quint64), 和 endMap

bool QCborStreamWriter::endMap()

通过 startMap() 的任一重载启动映射并返回 true,如果已向映射添加正确的元素数量。对于使用的每个 startMap() 必须调用此函数。

返回值为 false 表明应用程序中存在错误,并且在此流中发生不可恢复的错误。.QCborStreamWriter 还会在发生这种情况时使用 qWarning() 写入警告。

在当前容器不是一个映射的情况下调用此函数也是一个错误,尽管 QCborStreamWriter 目前无法检测此条件。

另请参阅 startMap(),startMap(quint64),以及 endArray()。

void QCborStreamWriter::setDevice(QIODevice *device)

将此 QCborStreamWriter 对象写入的设备或字节数组替换为 device

另请参阅 device

void QCborStreamWriter::startArray()

在 CBOR 流中启动具有不确定长度的 CBOR 数组。每个 startArray() 调用必须与一个 endArray() 调对齐,当前 CBOR 元素延伸到数组的结尾。

此函数创建的数组没有显式长度。相反,其长度由其中的元素隐式表示。但请注意,不确定长度数组的用法不符合标准 CBOR 编码。

下面的示例将字符串列表中的元素追加

   void appendList(QCborStreamWriter &writer, const QList<QString> &values)
   {
       writer.startArray();
       for (const QString &s : values)
           writer.append(s);
       writer.endArray();
   }

另请参阅 startArray(quint64),endArray(),startMap(),QCborStreamReader::isArray(),和 QCborStreamReader::isLengthKnown()。

void QCborStreamWriter::startArray(quint64 count)

这是一个重载的函数。

在 CBOR 流中启动具有显式长度为 count 项的 CBOR 数组。每个 startArray 调用必须与一个 endArray() 调对齐,当前 CBOR 元素延伸到数组的结尾。

此函数创建的数组具有显式长度,因此必须将 exactly count 项添加到 CBOR 流中。添加较少或较多的项将导致 endArray() 时失败,并且 CBOR 流将损坏。但是,显式长度数组是标准 CBOR 编码的必需品。

下面的示例将输入的 QStringList 中找到的所有字符串追加

   void appendList(QCborStreamWriter &writer, const QStringList &list)
   {
       writer.startArray(list.size());
       for (const QString &s : list)
           writer.append(s);
       writer.endArray();
   }

大小限制:此函数的参数是 quint64,这似乎允许在数组中最多有 264-1 个元素。但是,QCborStreamWriterQCborStreamReader 目前在 32 位系统上限制为 232-2 个项目,在 64 位系统上限制为 264-2 个项目。另外,请注意 QCborArray 目前在 32 位平台上限制为 227 个元素,在 64 位平台上限制为 259 个元素。

另请参阅 startArray(),endArray(),startMap(),QCborStreamReader::isArray(),和 QCborStreamReader::isLengthKnown()。

void QCborStreamWriter::startMap()

在 CBOR 流中启动具有不确定长度的 CBOR 映射。每个 startMap() 调用必须与一个 endMap() 调对齐,当前 CBOR 元素延伸到映射的结尾。

此函数创建的映射没有显式长度。相反,其长度由其中的元素隐式表示。但请注意,不确定长度映射的使用不符合标准 CBOR 编码(标准编码还要求键是唯一的并按顺序排列)。

以下示例将输入的整型和字符串对列表中的元素附加到列表中

   void appendMap(QCborStreamWriter &writer, const QList<std::pair<int, QString>> &values)
   {
       writer.startMap();
       for (const auto pair : values) {
           writer.append(pair.first)
           writer.append(pair.second);
       }
       writer.endMap();
   }

另请参阅 startMap(quint64), endMap(), startArray(), QCborStreamReader::isMap(),以及QCborStreamReader::isLengthKnown().

void QCborStreamWriter::startMap(quint64 count)

这是一个重载的函数。

在CBOR流中启动具有显式长度为 count 个项目的CBOR Map。每个startMap调用必须与一个endMap()调用配对,并且当前的CBOR元素扩展到地图的末尾。

此函数创建的地图具有显式长度,因此必须在CBOR流中添加恰好count对项。添加更少或更多的项将在endMap()时失败,并导致CBOR流损坏。但是,显式长度地图是规范CBOR编解码所必需的。

以下示例将输入的QMap中找到的所有字符串附加到列表中

   void appendMap(QCborStreamWriter &writer, const QMap<int, QString> &map)
   {
       writer.startMap(map.size());
       for (auto it = map.cbegin(), end = map.cend(); it != end; ++it) {
           writer.append(it.key());
           writer.append(it.value());
       }
       writer.endMap();
   }

大小限制:此函数的参数是quint64,似乎允许在地图中有264-1对。但是,QCborStreamWriterQCborStreamReader目前都限制在32位系统上的231-1个项和在64位系统上的263-1个项。另外,请注意,QCborMap目前限制在32位平台上的226个元素和在64位平台上的258个元素。

另请参阅 startMap(), endMap(), startArray(), QCborStreamReader::isMap(),以及QCborStreamReader::isLengthKnown().

© 2024 Qt公司 Ltd. 本文档贡献的版权属于其各自的所有者。本处提供的文档是以自由软件基金会发布的GNU自由文档许可(FDL)1.3版许可条款提供的。Qt及其相关标志是芬兰和/或世界其他地区的Qt公司 Ltd的商标。所有其他商标均为各自所有者的财产。