C++ 以人类可读的形式将自定义QMap模板实例化保存在QSettings中
在我的代码中,我使用QSettings机制将自己的类C++ 以人类可读的形式将自定义QMap模板实例化保存在QSettings中,c++,qt,serialization,qvariant,qsettings,C++,Qt,Serialization,Qvariant,Qsettings,在我的代码中,我使用QSettings机制将自己的类MyClass保存并加载到QMap配置文件中 我知道如何将我自己的类型注册到QMetaObject,以便可以将它们与QVariant一起使用。这允许使用QSettings保存它们。请参阅下面的工作代码 然而,在我正在编写的实际配置文件中,这些类型的表示方式决不是人类可读的是否有任何方法使自定义映射在文本编辑器中更具可读性,以便我可以在Qt之外手动更改配置? 将自定义类型保存到配置的代码: struct MyClass { unsigne
MyClass
保存并加载到QMap
配置文件中
我知道如何将我自己的类型注册到QMetaObject,以便可以将它们与QVariant一起使用。这允许使用QSettings保存它们。请参阅下面的工作代码
然而,在我正在编写的实际配置文件中,这些类型的表示方式决不是人类可读的是否有任何方法使自定义映射在文本编辑器中更具可读性,以便我可以在Qt之外手动更改配置?
将自定义类型保存到配置的代码:
struct MyClass
{
unsigned int id;
QString name;
QString value;
friend QDataStream & operator<< (QDataStream &arch, const MyClass& c)
{
return arch << c.id << c.name << c.value;
}
friend QDataStream & operator>> (QDataStream &arch, MyClass& c)
{
return arch >> c.id >> c.name >> c.value;
}
};
Q_DECLARE_METATYPE(MyClass)
typedef QMap<unsigned int, MyClass> MyMap;
int main(int argc, char *argv[])
{
MyMap map;
map.insert(100, {100, "name1", "value1"});
map.insert(101, {101, "name2", "value2"});
map.insert(200, {200, "name3", "value3"});
qRegisterMetaTypeStreamOperators<MyMap>("MyMap");
QSettings conf("/home/dave/temp/myfile.conf", QSettings::IniFormat);
conf.setValue("myMapping", QVariant::fromValue(map));
conf.sync();
}
struct MyClass
{
无符号整数id;
QString名称;
QString值;
friend QDataStream&运算符c.id>>c.name>>c.value;
}
};
Q_DECLARE_元类型(MyClass)
typedef-QMap-MyMap;
int main(int argc,char*argv[])
{
我的地图;
插入(100,{100,“名称1”,“值1”});
插入(101,{101,“名称2”,“值2”});
插入(200,{200,“名称3”,“值3”});
qRegisterMetaTypeStreamOperators(“MyMap”);
QSettings-conf(“/home/dave/temp/myfile.conf”,QSettings::ini格式);
conf.setValue(“myMapping”,QVariant::fromValue(map));
conf.sync();
}
写入的配置文件:
[General]
myMapping="@Variant(\0\0\0\x7f\0\0\0\x13QMap<uint,MyClass>\0\0\0\0\x3\0\0\0\xc8\0\0\0\xc8\0\0\0\n\0n\0\x61\0m\0\x65\0\x33\0\0\0\f\0v\0\x61\0l\0u\0\x65\0\x33\0\0\0\x65\0\0\0\x65\0\0\0\n\0n\0\x61\0m\0\x65\0\x32\0\0\0\f\0v\0\x61\0l\0u\0\x65\0\x32\0\0\0\x64\0\0\0\x64\0\0\0\n\0n\0\x61\0m\0\x65\0\x31\0\0\0\f\0v\0\x61\0l\0u\0\x65\0\x31)"
[概述]
1.0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0 0\x32\0\0\0\x64\0\0\0\x64\0\0\0\n\0n\0\x61\0m\0\x65\0\x31\0\0\0\0\f\0v\0\x61\0l\0u\0\x65\0\x31)”
Qt负责对地图进行序列化/反序列化-不幸的是,这并没有考虑人类的可读性
您需要手动处理整个映射的序列化/反序列化,并写入/读取QString(或类似的内容),例如
QString序列化(常量QMap和映射序列化)
{
QStringList结果;
for(int键:mapToSerialize.keys())
{
result.append(“%1%2%3”).arg(QString::number(i),SEPARATOR_标记,serialize(mapToSerialize.value(i));
}
返回result.join(映射分隔符标记);
}
这当然有缺点,1)需要为映射和类编写序列化/反序列化函数,2)需要处理所有特殊情况(转义特殊字符、解析错误数据等)Qt负责对地图进行序列化/反序列化-不幸的是,这并没有考虑人类的可读性 您需要手动处理整个映射的序列化/反序列化,并写入/读取QString(或类似的内容),例如
QString序列化(常量QMap和映射序列化)
{
QStringList结果;
for(int键:mapToSerialize.keys())
{
result.append(“%1%2%3”).arg(QString::number(i),SEPARATOR_标记,serialize(mapToSerialize.value(i));
}
返回result.join(映射分隔符标记);
}
这当然有缺点,1)需要为映射和类编写序列化/反序列化函数,2)需要处理所有特殊情况(转义特殊字符、解析错误数据等)
QString serialize(const QMap<int, MyClass>& mapToSerialize)
{
QStringList result;
for(int key : mapToSerialize.keys())
{
result.append("%1%2%3).arg(QString::number(i), SEPARATOR_TOKEN, serialize(mapToSerialize.value(i));
}
return result.join(MAP_SEPARATOR_TOKEN);
}