在C ++ / Qt中以文本格式序列化数据结构

时间:2013-10-04 16:07:04

标签: c++ sql qt

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

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

非常感谢提前!

3 个答案:

答案 0 :(得分:5)

  

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

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

你应该考虑的事情:

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

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

      如果您正在与某些内容进行通信,那么您将无法使用与之通信的任何格式。这可能是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类型作为值。即您可以轻松转储QColorQPoint,以及您在其中注册的类型。您可以存储在QVariant中的任何内容,您可以存储在QVariantMap中,然后可以在一行代码中将其序列化为QDataStream。

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

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

答案 1 :(得分: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 &);

答案 2 :(得分:3)

这是一个冗长而详细的答案,但这里是重点。 Qt 5.2有一个例子,你可以用Qt实现所有这些,基于“SaveGame”示例,它也在进行序列化和反序列化。它基本上是为不可玩的游戏角色做的。它还使用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,因此应该适合您。在这里,您可以找到如何序列化和反序列化此类型的签名:

序列化

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的。