彻底解决QT编码问题

彻底解决QT编码问题

字符串常量、"中文"是传统的char类型的窄字符串、在使用的时候只需要告诉QString这两个汉字采用的编码构造QString。

const char * str = "中文";
QString qstr = str;   //相当于调用QString::QString(const char * str)初始化一个QString

概念1:源文件是有编码的
"中文" 在不同的编码下对应不同的二进制形式
可能在GBK编码下是:ce d2 ca c7
在Latin-1编码下是:ba ba d7 d6

概念2:QString内部采用的是Unicode

一个问题,源代码中假如有4个字节"xcexd2xcaxc7“该怎么转换成Unicode并存储在QString内。按照GBK、BIG5、Latin-1还是其他方式...
在你不告诉它的情况下,它默认选择了Latin-1,于是4个字符"ÎÒÊÇ"的unicode码被存进了QString中。最终,4个Latin字符出现在你期盼看到2中文字符的地方,所谓的乱码出现了

解决方式

问题很简单,当你需要从窄字符串 char* 转成Unicode的QString字符串的,你需要告诉QString你的这串char* 中究竟是什么编码?GBK、BIG5、Latin-1
理想情况就是:将char* 传给QString时,同时告诉QString自己的编码是什么

就像下面的函数一样,QString的成员函数知道按照何种编码来处理 C 字符串
QString QString::fromAscii ( const char * str, int size = -1 )
QString QString::fromLatin1 ( const char * str, int size = -1 ) 
QString QString::fromLocal8Bit ( const char * str, int size = -1 )
QString QString::fromUtf8 ( const char * str, int size = -1 )
QString 只提供了这几个成员函数,远远满足不了大家的需求,比如,在简体中文Windows下,local8Bit是GBK,可是有一个char串是 BIG5 或 Latin-2怎么办?

可以使用强大的QTextCodec,首先QTextCodec肯定知道自己所负责的编码的,当你把一个char串送给它,就能正确将其转成Unicode
QString QTextCodec::toUnicode ( const char * chars ) const

可是这个调用太麻烦了
想直接
QString a= str;
QString a(str);

这样一来肯定没办法同时告诉 QString 你的str是何种编码了,只能通过其他方式了。
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
设置QString默认采用的编码。而究竟采用哪一个,一般来说就是源代码是GBK,就用GBK,源代码是UTF-8就用UTF-8。但有一个例外,如果你保存成了带BOM的UTF-8而且用的微软的cl编译器,此时仍是GBK。

总结

QString内部采用的是 Unicode,它可以同时存放GBK中的字符"我是汉字",BIG5中的字符"扂岆犖趼" 以及Latin-1中的字符"ÎÒÊǺº×Ö"。

当你需要从窄字符串 char* 转成Unicode的QString字符串的,你需要告诉QString你的这串char* 中究竟是什么编码?GBK、BIG5、Latin-1?

在你不告诉它的情况下,它默认选择了Latin-1,于是8个字符"ÎÒÊǺº×Ö"的unicode码被存进了QString中。最终,8个Latin字符出现在你期盼看到4中文字符的地方,

所谓的乱码出现了。

网上有很多方法介绍直接在main.cpp里设置:

QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForTr(codec);
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);

其实这在某些情况下也是有问题的,因为程序可能读到系统的中文路径,或者调用中文路径下的外部程序,这时候如果系统是gb2312就有问题了。

因为中文路径的编码是采用utf-8存到QString里的,系统读中文路径解码的时候采用的却是系统的gb2312,所以会调不起带中文路径的外部程序。

以上问题下面方法可以解决:

QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForTr(codec);
QTextCodec::setCodecForLocale(QTextCodec::codecForLocale()); //设置GBK到本地
QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());

对于外部字符串编码解码全部采用本地编码。

在QT5中,加上这句,源文件使用UTF-8编码,不带BOM
QApplication a(argc, argv);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
原文地址:https://www.cnblogs.com/liunian1004/p/5912536.html