C++ QSettings不区分字符串和int值

C++ QSettings不区分字符串和int值,c++,qt,types,qsettings,C++,Qt,Types,Qsettings,我正在使用文件备份的QSettings对象写入和读取字符串和int值。 当我稍后尝试从另一个进程读取值时,这些值被读取为字符串而不是int 这是我用来写值的代码: QSettings settings("TestQSettings.ini", QSettings::IniFormat); settings.setValue("AAA",QString("111")); settings.setValue("BBB",222); 这是创建的文件: 这是我用来读取值的代码: QVariant q

我正在使用文件备份的
QSettings
对象写入和读取字符串和int值。 当我稍后尝试从另一个进程读取值时,这些值被读取为字符串而不是int

这是我用来写值的代码:

QSettings settings("TestQSettings.ini", QSettings::IniFormat);
settings.setValue("AAA",QString("111"));
settings.setValue("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;
如果我从其他进程运行此代码:

我知道在读取类型之后可以转换它们。 不幸的是,此解决方案需要修改我不愿意修改的Windows遗留跨平台代码,例如对
RegQueryValueEx()
的多次调用

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

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

[General]
AAA="111"
BBB=222

这个问题在Linux上的Qt4和Qt5上都存在。

哇哇哇,您使用的是.ini文件还是注册表

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

使用注册表,
QSettings
将按照您的预期工作

我真的不明白问题出在哪里。如果希望保留类型信息,请不要使用
.ini
文件。如果以依赖于平台的方式手工编写代码,您将面临完全相同的问题


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

结果表明,解决方案非常简单

将值写入INI文件时,类型已知。 我在SetValue前面加上值“\”字符串

从INI文件读回值时。 我验证字符串类型是否具有上述后缀。 如果他们这样做,我就把后缀砍掉。 如果它们不是,我假设它们是整数而不是字符串

工作起来很有魅力


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

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

void store(QSettings& settings, const QString& key, const QVariant& value)
{
    settings.setValue(key+"value", value);
    settings.setValue(key+"type", value.typeName());
}
回读时,我们还读取类型名称,如果变量的类型不正确,则在返回之前读取变量

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;
}
QVariant检索(常量QSettings&settings,常量QString&key)
{
自动值=设置值(键+值);
const auto typeName=settings.value(key+“type”).toString();
const bool wasNull=value.isNull();//注意1
const auto t=QMetaType::type(typeName.toUtf8());//注意2
if(value.userType()!=t&&!value.convert(t)&&&!wasNull){
//还原由失败的转换()清除的值
值=设置值(键+值);

qWarning()我在你的帖子中找不到一个实际的问题。而且我担心
.ini
文件不存储类型信息,因此如果问题是“我如何使
.ini
文件保持类型”,那么答案恐怕是“你没有”您的程序应该知道其ini文件的类型。因此,如果您在其中存储int,请将QVariant转换为整数,如果失败,则抛出异常…简单到这一点更新了问题。修改代码并不是那么简单,因为我正在为来自另一个项目的Windows注册表调用进行包装。调用太多,会导致错误d我不想对代码进行太多修改。我在Linux上使用ini文件。我在Linux上使用ini文件。但是我正在编译的代码与Windows项目共享,应该为两种平台编译。我正在研究大小为1的QStringList。这看起来很有希望。如果我在字符串的两侧添加引号,字符串将以0存储把引文删掉。
[General]
AAA="111"
BBB=222
void store(QSettings& settings, const QString& key, const QVariant& value)
{
    settings.setValue(key+"value", value);
    settings.setValue(key+"type", value.typeName());
}
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;
}