【问题标题】:Serialize a data structure in text format in C++/Qt在 C++/Qt 中以文本格式序列化数据结构
【发布时间】:2013-10-06 02:45:02
【问题描述】:

我需要将一些数据结构存储到 SQL 数据库中。这些数据可能会有所不同,所以我不知道数据库必须有哪些字段。我即将将数据结构编码为 XML 或 JSON 对象,然后将其放入 SQL 数据库。但它不起作用,所以我需要序列化,因为问题在于编码该结构。

我可以使用哪个库/工具/方法将数据结构序列化/反序列化为文本?假设一个由一些整数、一些 Unicode 字符串和一些布尔值组成的数据结构。

非常感谢!

【问题讨论】:

  • @CapelliC:Qt 有 QTextStream + QXmlWriter。至少 Qt 4。 Qt 5 应该有内置的 json 支持。而且你可以随时序列化你想要的任何东西,因为 QVariantMap 保存为二进制 blob。
  • @SigTerm:我知道,但也许 OP' 的问题更微妙:我认为他正在寻找能够在关系中解构/重组 Qt 对象的东西。也许 Postgres 可以提供一些东西......
  • 真的很长,很有趣,很好的答案!太感谢了。即便如此,如果没有评论,请不要理解反对票。
  • @DídacPérez:别担心,我也有一个,但我不明白。我们需要忍受这些并继续前进。 :)
  • @DídacPérez 我没有投反对票,但你的问题是“我正在寻找一种工具来做 X”的品种,它经常被关闭,而且它也没有显示结果任何严肃的研究,例如详细说明您尝试过的内容以及您在该主题上搜索过的内容。这就是我对它为什么被否决的预感。

标签: c++ sql qt


【解决方案1】:

因为问题在于对该结构进行编码。

Qt 不能自动序列化事物,因此您必须编写某种例程来保存/加载数据。确切的解决方案取决于您的要求以及您将如何使用数据。

您应该考虑的事项:

  1. 是否需要人类可读性? (由于解析,加载文本文件可能会更慢)
  2. 是否需要通信/数据交换(与其他程序)?
  3. 什么是最便宜的开发解决方案?

推荐:

  1. 如果数据很简单,仅供您的应用使用,二进制(非人类可读),则使用QDataStream + QByteArray,手动序列化。
  2. 如果数据很复杂,仅由您的应用程序使用,二进制(非人类可读),则使用QDataStream + QByteArray + QVariantMap。 (将数据转储到 qvariant 映射中,然后使用 QDataStream 将其序列化为 QByteArray)
  3. 如果数据很简单,仅由您的应用使用,文本(应该是人类可读的)然后是纯文本、json 或 xml。
  4. 如果数据很复杂,仅由您的应用程序使用,文本(人类可读),然后使用 json 或 xml - 取决于哪个可用/哪个最短。
  5. 如果数据应该由某个第 3 方工具读取,则使用该工具使用的任何格式。

详情:

如果您正在与某物交流,您会被与您交流的东西所使用的任何格式所困。那可能是 json 或 xml,因为各种脚本语言经常可以轻松读取它们中的任何一个

如果数据应该是人类可读的,那么您有以下选项:纯文本、json 或 xml,具体取决于数据格式/复杂性。 (ini 在您的场景中不起作用,因为 QSettings 支持它并不会真正序列化到内存中的随机位置。xml/json)可以存储树状结构,但 json 仅在 Qt 4 中可用通过外部依赖,xml reader/writer 需要努力才能掌握它。

如果您想存储 非人类可读且仅由您的应用程序使用的私有数据(仅由您的应用程序使用),您几乎可以使用任何东西你想要的,包括二进制格式。

最简单的方法是手动将其转储到QByteArray + QDataStream,因为QDataStream 保证二进制数据将在任何平台上正确加载,无论字节顺序如何(只要您不将其转储为一个原始内存块,即)。如果数据是具有固定数量且始终存在的组件的类似结构的简单数组,那将可以正常工作。

如果数据是树状的并且具有可选节点(即键值对树,其中值可以是另一棵树)并且键可能存在也可能不存在,那么您将使用处理这些键的库或例程/值对树。 在 Qt 4 中是 QVariantMap 和 xml(通过 QXmlStreamWriter/QXmlStreamReader)。 Qt 5 也有 json 支持。在有多种解决方案可用的情况下,实施起来花费最少的内置解决方案会胜出。从QVariantMap 读取命名字段每个值需要 1 行代码 + 大约 10 行代码的辅助函数,它还支持所有 Qt 4 类型。

QVariantMap 在某种意义上具有其他 json 的显着优势,因为它本机支持所有 Qt 类型作为值。 IE。您可以轻松转储QColorQPoint,以及您在其中注册的类型。您可以存储在 QVariant 中的任何内容都可以存储在 QVariantMap 中,然后可以在一行代码中将其序列化到 QDataStream 或从 QDataStream 序列化。

另一方面,Json 具有可以在脚本语言中加载的“标准”数据格式的优势。这是以仅支持 6 种基本类型为代价的。

Qt 4 本身不支持 Json,虽然有 QJson,但添加外部依赖项并不总是一个好主意,因为你要照看它们。如果您使用的是 Qt 4 并且确实需要 json 支持,那么升级到 Qt 5 可能是有意义的。

【讨论】:

    【解决方案2】:

    您如何处理数据库中的这些数据?如果您想在其他程序或语言中使用它,那么您的数据需要是可读的,您可以使用 QXmlStreamWriter/Reader 或 QJsonDocument(两者都带有 QByteArray)。

    如果你不想在你的程序之外使用你的数据,你可以用 QDataStream 将它们写在 QByteArray 中。

    类似于下面的代码。

    QByteArray data;
    QDataStream stream(&data);
    stream << yourClasses;
    sqlQuery.bindValue(data);
    

    您只需在要序列化的类中添加流运算符:

    QDataStream &operator<<(QDataStream &, A const&);
    QDataStream &operator>>(QDataStream &, A &);
    

    【讨论】:

      【解决方案3】:

      这是一个冗长而详细的答案,但重点在这里。 Qt 5.2 有一个示例,您可以如何使用基于“SaveGame”示例的 Qt 实现所有这些,该示例也进行序列化和反序列化。它基本上是为不可玩的游戏角色做的。它还使用QSaveFile 将信息安全地保存到所需的文件中。为方便起见,您可以在此处找到示例文档的 url:

      http://doc-snapshot.qt-project.org/qdoc/qtcore-savegame-example.html

      几天前我刚刚用 Qt5 的 json 解析器解决了这个问题。我建议看看以下课程:

      如果您计划使用 Qt 4,您将需要使用 QJson 库,但请注意,基于性能,它比 Qt 5 json 解析器慢很多。在这里您可以找到蒂亚戈的基准:

      https://plus.google.com/108138837678270193032/posts/7EVTACgwtxK

      json 格式可以随心所欲地支持字符串、整数和布尔值,所以它应该适合你。在这里您可以找到如何序列化和反序列化此类类型的签名:

      序列化

      bool    toBool(bool defaultValue = false) const
      double  toDouble(double defaultValue = 0) const
      QString toString(const QString & defaultValue = QString()) const
      

      反序列化

      QJsonValue(bool b)
      QJsonValue(double n)
      QJsonValue(const QString & s)
      

      在这里您可以找到关于 Qt 5 中 json 支持的摘要页面:

      http://doc-snapshot.qt-project.org/qt5-nosubdir/json.html

      请注意,Qt 5 的 json 在内部保存为一种非常有效的二进制表示形式,因此本质上您也可以使用它而不是文本表示形式。这取决于您的确切情况。实际上,对于 Qt 4,如果需要,您甚至可以向后移植这些类,因为它们与 Qt 5 紧密相关。对于 BlackBerry 开发而言,实际上可能是如此,因为我们在那里与 Qt 4 苦苦挣扎,我们非常需要来自的 json 解析器Qt。

      【讨论】:

      • 我认为这个答案错过了提问者想要做的事情的重点:你有一个 C++ 结构,你想用最少的样板进行序列化——甚至可能为零。 savegame 示例使用手写代码手动序列化结构。
      • @KubaOber:您可以根据答案在 Qt 5 中使用零样板序列化和反序列化 json。
      猜你喜欢
      • 2010-09-27
      • 1970-01-01
      • 2016-05-02
      • 1970-01-01
      • 1970-01-01
      • 2016-03-05
      • 1970-01-01
      • 2015-01-05
      • 2021-09-21
      相关资源
      最近更新 更多