【问题标题】:Save Configuration Settings to XML file in QT?将配置设置保存到 QT 中的 XML 文件?
【发布时间】:2011-09-29 10:35:28
【问题描述】:

我想将配置设置保存到 QT 中的 XML 文件并从那里读取?

在 QT 中执行此操作的最佳方法是什么?

非常感谢任何示例/想法。

谢谢。

【问题讨论】:

  • 如果你不一定需要XML,你可以去QSettings。否则,您需要使用 QXmlStreamReader/Writer 或 QDomDocument 解析和写入 XML。
  • @Frank : 你能给我一些简单的例子来理解 QSettings 吗?
  • QSettings 文档应该包含足够多的示例?

标签: qt configuration settings configuration-files


【解决方案1】:

您可以使用QSettings::registerFormat注册您的 XML 文件格式

这是readXmlFile and writeXmlFile 的示例实现

【讨论】:

  • 但我猜 Qsettings 会保存在内存中。我想保存 2 个文件并从那里读取它...
  • 示例实现使用QXmlStreamWriter将配置文件保存在QIODevice的实例中,通常是QFile
  • 示例实现根本不能与键值对的 QSettings 内部表示一起工作。例如如果您使用 beginWriteArray/endArray 将数组写入 QSettings,则 writer 函数会写入格式非常糟糕的 XML,其中包含以数字 (Value1>) 开头的数组元素的标记名称。这是非法的。到目前为止,我还没有遇到考虑到“数组”的有效读/写 XML 实现。
【解决方案2】:

这是我将设置导出到 XML 的代码。您需要调用ExportSettingsToXml() 并打开以编写QFile。导出的文件可以用ImportSettingsFromXml()再次导入。

QString Variant2Text( const QVariant &value )
{
    switch (value.type())
    {
    case QVariant::String:
    case QVariant::Int:
    case QVariant::UInt:
    case QVariant::LongLong:
    case QVariant::ULongLong:
    case QVariant::Double:
    case QVariant::Bool:
        return value.toString();
    }

    QByteArray ba;
    value.save(QDataStream(&ba, QIODevice::WriteOnly));

    return QString(ba.toHex());
}

QVariant Text2Variant( const QString &sText, QVariant::Type nType )
{
    switch (nType)
    {
    case QVariant::String:
    case QVariant::Int:
    case QVariant::UInt:
    case QVariant::LongLong:
    case QVariant::ULongLong:
    case QVariant::Double:
    case QVariant::Bool:
        {
            QVariant var(sText);
            if (var.convert(nType))
                return var;

            return QVariant(sText);
        }
        return QVariant::fromValue(sText);
    }

    QVariant value;
    value.load(QDataStream(&QByteArray::fromHex(sText.toLatin1()), QIODevice::ReadOnly));

    return value;
}

void XmlExportSettingsRecursive(QXmlStreamWriter &writer, QSettings &settings, const QStringList &blackList)
{
    QString sGroup = settings.group();

    if (!sGroup.isEmpty())
    {
        writer.writeStartElement("group");  
        writer.writeAttribute(QStringLiteral("name"), sGroup.mid(sGroup.indexOf(QChar('/')) + 1));
    }
    // Write child groups first
    {
        const QStringList &listGroups = settings.childGroups();
        foreach (const QString &group, listGroups)
        {
            settings.beginGroup(group);         
            XmlExportSettingsRecursive(writer, settings, blackList);
            settings.endGroup();
        }
    }

    const QStringList &listKeys = settings.childKeys();
    foreach (const QString &key, listKeys)
    {
        if (blackList.contains(key))
            continue;

        writer.writeStartElement("key");
        writer.writeAttribute(QStringLiteral("name"), key);
        const QVariant &value = settings.value(key);
        writer.writeAttribute(QStringLiteral("type"), value.typeName());
        writer.writeCharacters(Variant2Text(value));
        writer.writeEndElement();
    }

    if (!sGroup.isEmpty())
        writer.writeEndElement();
}

bool XmlImportSettingsRecursive(QXmlStreamReader &reader, QSettings &settings)
{
    while (!reader.atEnd()) {
        reader.readNext();
        if (reader.isStartElement())
        {           
            if (reader.name() == QStringLiteral("group"))
            {
                const QXmlStreamAttributes &attr = reader.attributes();
                QString sGroup = attr.value(QStringLiteral("name")).toString();

                settings.beginGroup(sGroup);
                if (!XmlImportSettingsRecursive(reader, settings))
                    return false;
                settings.endGroup();
            }
            else if (reader.name() == QStringLiteral("key"))
            {
                const QXmlStreamAttributes &attr = reader.attributes();
                const QString &sKey = attr.value(QStringLiteral("name")).toString();
                const QString &sType = attr.value(QStringLiteral("type")).toString();
                if (reader.readNext())
                {
                    if (reader.isCharacters() || reader.isEndElement())
                    {
                        const QString &sValue = reader.text().toString();
                        settings.setValue(sKey, Text2Variant(sValue, QVariant::nameToType(sType.toLatin1())));
                    }
                    else
                        continue;
                }
            }
        }
        else if (reader.isEndElement() && reader.name() == QStringLiteral("group"))
            return true;
    }
    if (reader.hasError()) {
        qDebug()<<reader.errorString();
        return false;
    }

    return true;
}

bool ExportSettingsToXml( QIODevice *device, const QString &settingsGroup = QString(), const QStringList &blackList = QStringList())
{   
    if (!device || !device->isWritable())
        return false;

    QSettings settings;
    settings.beginGroup(settingsGroup);

    QXmlStreamWriter xmlWriter( device );
    xmlWriter.setAutoFormatting( true );
    xmlWriter.writeStartDocument();

    xmlWriter.writeStartElement( QStringLiteral("settings") );

    if (!settingsGroup.isEmpty())
    {   
        xmlWriter.writeStartElement(QStringLiteral("group"));
        xmlWriter.writeAttribute(QStringLiteral("name"), settingsGroup);
    }

    XmlExportSettingsRecursive(xmlWriter, settings, blackList);

    if (!settingsGroup.isEmpty())
        xmlWriter.writeEndElement();

    xmlWriter.writeEndDocument();

    return true;
}

bool ImportSettingsFromXml( QIODevice *device, const QString &settingsGroup = QString())
{
    if (!device || !device->isReadable())
    {
        qDebug()<<"Trying to import XML settings from non-readable device";
        return false;
    }

    QSettings settings;
    settings.beginGroup(settingsGroup);
    QXmlStreamReader xmlReader( device );
    xmlReader.readNext();
    if (!xmlReader.isStartDocument())
    {
        qDebug()<<"Invalid xml document format";
        return false;
    }

    if (!xmlReader.readNextStartElement())
    {
        qDebug()<<"Empty settings xml document";
        return true;
    }

    if (xmlReader.name() == QStringLiteral("settings") )
    {
        if (!XmlImportSettingsRecursive(xmlReader, settings))
            return false;
    }
    else
    {
        qDebug()<<"Unknown settings format.";
        return false;
    }

    return true;
}

【讨论】:

    【解决方案3】:

    对于这样的事情,我经常将boost library 用于 C+ 并且强烈推荐它。它提供各种格式的序列化,如 XML、文本、二进制等。

    Serialization Tutorial(看起来比实际复杂)

    【讨论】:

    • Qt 在与自己一起工作时发挥最佳效果。 Boost 很好,但集成起来会很麻烦,除非它封装在 Qt 格式中。为什么要引入另一个库依赖项?
    • 没错,这是另一个依赖项。这只是我个人对boost的体验。易于使用、快速和增强包括还没有让我的项目混乱
    【解决方案4】:

    There 是 XML 的 Qt 示例。

    您也可以使用QSettings 来存储您的设置。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-12
      • 2011-05-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多