我正在使用文件支持的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都存在此问题。
答案 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;
}
由于wasNull
的这个小问题,convert()
变量就在那里:
警告:由于历史原因,转换空
QVariant
会导致所需类型的空值(例如,QString
的空字符串)和结果false
。
在这种情况下,我们需要忽略误导性的返回值,并保持正确类型的成功转换的null变体。
目前尚不清楚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实际上提供了解决方案。