1

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

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

提前谢谢了!

4

3 回答 3

5

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

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

你应该考虑的事情:

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

推荐:

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

细节:

如果您正在与某物进行通信,那么您将被与您与之通信的事物所使用的任何格式所困。那可能是 json 或 xml,因为各种脚本语言经常可以很容易地读取它们中的任何一个

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

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

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

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

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

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

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

于 2013-10-04T21:15:10.477 回答
4

您如何处理数据库中的这些数据?如果您想在其他程序或语言中使用它,那么您的数据需要是可读的,您可以使用 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 &);
于 2013-10-04T17:18:02.130 回答
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。

于 2013-10-04T19:39:30.853 回答