我们在QSettings 与中文 一文中认识了QSettings在Qt4.5中引入的setIniCodec成员函数。
这是一个挺不错的函数,估计解决了不少人的中文(我自己几乎不在里面用中文,感受不是太深)。
这两天看Qt的bugreport,发现这个看似无害的便利函数还是直接导致了一些 bug:
是一个这样的问题:
bug提交者给出的代码如下:
#include <QtCore/QCoreApplication> #include <QSettings> #include <QDebug> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); { QSettings set("settings.ini",QSettings::IniFormat,0); set.setIniCodec("cp1251"); QByteArray ba; ba.resize(256); for(int i=0;i<ba.size();i++){ ba[i]=i; } set.setValue("array",ba); } { QSettings set("settings.ini",QSettings::IniFormat,0); set.setIniCodec("cp1251"); QByteArray ba=set.value("array").toByteArray(); qDebug()<<"size="<<ba.size(); for(int i=0;i<ba.size();i++){ if((uchar)ba.at(i)!=i){ qDebug()<<"Error: "<<i<<"!="<<(uchar)ba.at(i); break; } } } return 0; }
我们在QSettings 与中文 一文中涉及到这部分内容。
QSettings 的核心是 一个QMap<QString, QVariant> ,key是一个QString,value是QVariant类型
回头看这个bug:
QByteArray 对象存放在QVariant中,第一步先变成QString:@ByteArray(.....)
括号内是QByteArray的真实内容"/x0/x1/x2.../x255" 对应的字符串。其实这是通过QString::fromLatin1()实现的
问题出来了:cp1251 无法对U+128U+129 等unicode字符进行解码,于是问号被写入了ini文件。
bug的修复:
是这样一个问题:
bug 提交者给出的代码如下
#include <QtCore/QCoreApplication> #include <QtCore/QSettings> #include <QtCore/QString> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QString v; { QSettings settings("test1.ini", QSettings::IniFormat); v = settings.value("lang").toString(); } QSettings settings1("test1.ini", QSettings::IniFormat); settings1.setIniCodec("UTF-8"); QString v1 = settings1.value("lang").toString(); return 0; }
QSettings 应该是处于性能上的考虑,会对读入的ini文件内容进行缓存。
这个bug产生的原因是:
如何修复:不太清楚该如何做,或许
http://bugreports.qt.nokia.com/browse/QTBUG-15543
http://bugreports.qt.nokia.com/browse/QTBUG-19552