`
duyouhua1214
  • 浏览: 228064 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

QSettings 与中文

    博客分类:
  • QT
 
阅读更多
本文介绍的是QSettings的 IniFormat 截止目前(Qt4.7)对中文的支持情况,如果你想实现自己定义格式(比如"[中文] 中文=中文"这样),可参看 QSettings 自定义格式

Qt4.4(包含)之前

先看个例子:

#

include <QtCore

/

QCoreApplication>




#

include <QtCore

/

QSettings>





int

 main

(int

 argc

, char

 **argv

)


{


    QCoreApplication

 app

(argc

, argv

);


    QString

 value

 = QString

::fromLocal8Bit

("

我是汉字

"

);


    QSettings

 settings

("

config.ini

"

, QSettings

::IniFormat

);


    settings

.setValue

("

setcion/key

"

, value

);



    return

 0

;


}

结果如下:

[setcion]
key=\x6211\x662f\x6c49\x5b57

这儿Value部分显示的是上面4个汉字的UCS2(即UTF-16)编码。如果你喜欢,你可以叫它“乱码”。

为什么四个汉字变成这个样子了呢?

因为4个汉字的Unicode编码超出了ASCII码的范围,而将其序列化的话,有很多种不同的方案,而这些不同的方案中,对特定的人来说,只有一种方案是最合适的,其他的可能都被这特定的人称作乱码。

众口难调啊?怎么办,那就不调了呗。直接给出UTF-16编码,这样一来,尽管每个人都不太喜欢,但总比让多数人都扫兴要好得多。

Qt4.5的转变

从Qt4.5开始,QSettings提供了一个新的成员函数,setIniCodec。这样一来,各种非ASCII码的用户应该高兴一点了,喜欢什么编码自己来设置,而不用考虑什么国际用户。

对简体中文用户来说,GBK还是UTF-8任意选择一个自己喜欢的就行了:

#

include <QtCore

/

QCoreApplication>




#

include <QtCore

/

QSettings>





int

 main

(int

 argc

, char

 **argv

)


{


    QCoreApplication

 app

(argc

, argv

);


    QString

 value

 = QString

::fromLocal8Bit

("

我是汉字

"

);


    QSettings

 settings

("

config.ini

"

, QSettings

::IniFormat

);


#

ifdef LOVE_GBK




    settings

.setIniCodec

("

GB2312

"

);


#

else




    settings

.setIniCodec

("

UTF8

"

);


#

endif




    settings

.setValue

("

setcion/key

"

, value

);



    return

 0

;


}

结果如下:

[setcion]
key=我是汉字

Key中的中文

截止到目前的Qt4.6.3,Key 和Section的中文仍不能使用本地编码,比如:

#

include <QtCore

/

QCoreApplication>




#

include <QtCore

/

QSettings>




#

include <QtCore

/

QStringBuilder>





int

 main

(int

 argc

, char

 **argv

)


{


    QCoreApplication

 app

(argc

, argv

);


    QString

 section

 = QString

::fromLocal8Bit

("



"

);


    QString

 key

 = QString

::fromLocal8Bit

("



"

);


    QString

 value

 = QString

::fromLocal8Bit

("

我是汉字

"

);


    QSettings

 settings

("

config.ini

"

, QSettings

::IniFormat

);


    settings

.setIniCodec

("

UTF-8

"

);


    settings

.setValue

(section

%"

/

"

%key

, value

);



    return

 0

;


}

注意:此处字符串连接用的Qt4.6引入的%,如果是之前的版本,换成+并删除相应头文件即可。

结果如下:

[%U8282]
%U952E=我是汉字

同一开始的Value一样,Key和Section中非ASCII字符的仍会进行转义,此处我们看到的就是%U后跟UTF-16的数值。该部分不受 setIniCodec的影响。

不止中文这样

其实不止中文是这样,Qt对传统的Latin系列编码也没有特殊的照顾

当Section Key Value中出现Latin字符时,同样将进行转义。比如:

#include <QtCore/QCoreApplication>
#include <QtCore/QSettings>
#include <QtCore/QStringBuilder>

int main(int argc, char **argv)
{
    QCoreApplication app(argc, argv);
    QString section = QString::fromLocal8Bit("ÀÁ");
    QString key = QString::fromLocal8Bit("ÀÁ");
    QString value = QString::fromLocal8Bit("ÀÁ");
    QSettings settings("config.ini", QSettings::IniFormat);
    settings.setValue(section%"/"%key, value);

    return 0;
}

结果:

[%E0%E1]
%E0%E1=\xe0\xe1

Settings源码

%QTDIR%\src\corelib\io\qsettings.cpp

QSettings的数据在内存中存放于 QMap<QString, QVariant> 中,读写文件也就是将文件读入该Map和从该Map写入文件的过程。

ini文件的写入

bool QConfFileSettingsPrivate::writeIniFile(QIODevice &device, const ParsedSettingsMap &map
)

Key的写入相对比较简单,因为本身就是字符串,只需序列化即可(对'0'-'9', 'a'-'z', 'A'-'Z', '_', '-', '.'之外的字符进行转义处理)。

void QSettingsPrivate::iniEscapedKey(const QString &key, QByteArray &result)

Value的写入就很复杂了,分两步走:

  • 将 QVariant 变成 QString 或 QStringList
    • StringList  和 List 型 ==> QStringList,其他转成QString

    • 直接转成字符串的 String  LongLong  Int Bool Double ...

    • 包含可读信息但不可直接转的 Rect Size Point ...
    • 包含非可读信息的  ByteArray

    • Invalid 型的 QVariant
    • 其他 QVariant
  • 将字符串序列化
    • 主要是对字符的Escape,比如'\0','\a'等控制字符,变成"\\0", "\\a"等
    • 其他控制字符,"\\x.."
    • 大于 7F 的字符,如有codec,则使用codec,如无,则用"\\x...."
    • 字符串内包含';', ',', '='时,字符串两段加引号
    • 字符'\0', "\x.."之后如果是数字(0-9a-fA-F),要继续如此处理

来源:http://hi.baidu.com/cyclone/blog/item/80a0793140fd3814eac4af7d.html

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics