QSettings不区分字符串和int值

时间:2013-10-14 07:12:14

标签: c++ qt types qsettings

我正在使用文件支持的QSettings对象编写和读取字符串和int值。 当我稍后尝试从不同的进程读取值时,值将被读取为字符串而不是int。

这是我用来写值的代码:

QSettings settings("TestQSettings.ini", QSettings::IniFormat);
settings.setValue("AAA",QString("111"));
settings.setValue("BBB",222);

这是创建的文件:

[General]
AAA=111
BBB=222

这是我用来读取值的代码:

QVariant qvar = settings.value("AAA");
std::cout << "AAA type " << qvar.type() << std::endl;
qvar = settings.value("BBB");
std::cout << "BBB type " << qvar.type() << std::endl;

如果我从同一个进程运行此代码:

AAA type 10
BBB type 2

如果我从不同的进程运行此代码:

AAA type 10
BBB type 10

我知道可以在阅读后转换类型。 遗憾的是,此解决方案需要修改我不想修改的Windows旧版跨平台代码,例如多次调用RegQueryValueEx()

是否可以存储和读取字符串和整数的类型信息?

例如,字符串将具有引号""而整数不会:

[General]
AAA="111"
BBB=222

在Linux上,Qt 4和Qt 5都存在此问题。

4 个答案:

答案 0 :(得分:1)

哇哇,你在使用.ini文件还是注册表?

使用.ini文件,显然不可能知道类型是什么,因为它只是一个字符串。您可以尝试将变量转换为整数(不要使用canConvert !),并假设它是一个整数,如果它转换为一个整数。

使用注册表,QSettings将按预期工作。

我真的不明白这是什么问题。如果您希望保留类型信息,请不要使用.ini文件。如果你以平台相关的方式手工编写代码,你将面临完全相同的问题。

您可以将引用的字符串显式写入.ini文件,并在读取时检查是否存在引号。如果引号不存在,您可以尝试转换为整数。

答案 1 :(得分:1)

我为一个需要保存和恢复任意类型变体的组件解决了这个问题,而不知道它的客户期望什么。解决方案是将变体typeName()与每个值一起存储:

void store(QSettings& settings, const QString& key, const QVariant& value)
{
    settings.setValue(key+"value", value);
    settings.setValue(key+"type", value.typeName());
}

回读时,我们还会在返回之前阅读类型名称和convert()变体(如果它不是正确的类型)。

QVariant retrieve(const QSettings& settings, const QString& key)
{
    auto value = settings.value(key+"value");
    const auto typeName = settings.value(key+"type").toString();

    const bool wasNull = value.isNull();                         // NOTE 1
    const auto t = QMetaType::type(typeName.toUtf8());           // NOTE 2

    if (value.userType() != t && !value.convert(t) && !wasNull) {
        // restore value that was cleared by the failed convert()
        value = settings.value(key+"value");
        qWarning() << "Failed to convert value" << value << "to" << typeName;
    }

    return value;
}

注释

  1. 由于wasNull的这个小问题,convert()变量就在那里:

      

    警告:由于历史原因,转换空QVariant会导致所需类型的空值(例如,QString的空字符串)和结果false

    在这种情况下,我们需要忽略误导性的返回值,并保持正确类型的成功转换的null变体。

    1. 目前尚不清楚UTF-8是QMetaType名称的正确编码(假设可能是本地8位?);我的类型都是ASCII,所以我只使用toLatin1()代替,这可能会更快。如果这是一个问题,我会在QString::fromLatin1方法中使用store()(而非隐式char*QString转化),以确保干净的往返

      如果找不到类型名称,t将为QMetaType::UnknownType;没关系,因为convert()将会失败,我们将返回未转换的变体(或null)。它不是很好,但它是一个在正常使用中不会发生的极端情况,我的系统会很快恢复。

答案 2 :(得分:0)

很明显。 QSettings使用QVariant来设置和获取值。

写作,settings.setValue("BBB",222);该值显式为QVariant的整数,因此QVariant::type()的结果为QVariant::Int

读取,INI文件不存储值的类型,一切都是字符串(例如,数字也将被读作字符串)。因此,QVariant::type()的结果是QVariant::String

不关心类型,QVariant对透明类型的差异,只需将它们转换为整数(如果不可能,将其作为错误输入处理)

答案 3 :(得分:0)

原来解决方案很简单。

将值写入INI文件时,类型已知。 我在SetValue

之前追加值“\”STRING

从INI文件中读取值时。 我验证字符串类型具有上述后缀。 如果他们这样做,我关闭后缀。 如果他们不这样做,我认为它们是整数而不是字符串。

像魅力一样!

感谢大家,尤其是@Kuba Ober实际上提供了解决方案。