Qt 5.x中出现中文乱码的解决方法

Qt 5.x中出现中文乱码的解决方法

中文乱码的问题,相信每个程序员都会遇到,并非Qt的特有,只是在使用Qt进行开发的过程中,总感觉有一种我去,Qt的字符串处理和编码以及国际化这些内容都做得挺好的,给我留一个中文乱码的问题,这就有点尴尬了,其实中文乱码的问题是C/C++与编译器的问题,不管是哪一类的编程语言都会遇到,出来混的迟早都是要还的,废话少扯,今天就对Qt 5.x中文乱码的问题作个了断。(Ps:为啥不是Qt呢?因为俺用的版本都是5.0以上的,而且在处理这个问题的过程中google出来的很多文章说的方法都是Qt 4.x版本的方法,对于5.0以上的版本基本上就无效了呀,当时我的内心是崩溃的,具体原因请看客接着看。。。)

  • 问题是什么:中文乱码
  • 为什么会出现问题:中文乱码产生的原因
  • 怎么解决:中文乱码的解决方法

问题是什么:中文乱码

1 使用Qt Creator打开代码,在编辑器中汉字就显示为乱码,在编辑器上方有明显的提示信息:

“Could not decode “…” with “UTF-8”encoding. Editing not possible.“

此时,有乱码的代码或者文档是不可编辑的,如图:
编辑乱码

2 在Qt Creator中显示的汉字正常,但在编译的过程中会出现”常量中有换行符”等一系列的错误和警告。归根来说,这也是文字编码的问题。如下图:
编译乱码

3 在Qt Creator中显示的汉字也正常,编译的过程中也没有出现任何问题,但在生成的程序中或者在执行时出现了乱码。(如:中文路径)如下图:
运行乱码

为什么会出现问题:中文乱码产生的原因

咱先不忙着解决问题,补点字符编码的东西:ASCIIGB2312GBKUnicodeUTF-8BOM这些东西是干啥的,源码字符集,执行字符集是什么?(Charset & Encoding源代码字符集和执行字符集

接着说我们的问题:
1 Qt Creator的编辑器默认使用UTF-8编码来读取文本文件,而微软的VS系列工具在创建文件和保存文件时默认以本地编码完成,对于中文版的windows系统,编码为GB2312。如果使用Qt Creator来读取编辑VS创建的文件,Qt编辑器就会以UTF-8的编码格式来读取GB2312编码格式的文件就会出现乱码,原因是UTF-8与GB2312对汉字的编码是不兼容的,而对英字字母这一类单字节字符是兼容的。

2 在安装Qt的时候,其实大家都知道,Qt本身是没有编译器的,它得依赖其他的编译器才能编译,在windows中,大部份使用的是vs编译工具链。所以在MSVC编译时,它会根据代码的文件有无BOM来定义源代码字符集。如果有BOM,则按BOM解释识别编码;如果没有,则使用本地字符集,对于windows中文系统而言就是GB2312。那么,当MSVC遇到一个没有BOM的utf-8编码的文件时,它通常会把文件看成GB2312来处理,如果文件全是英文,因为是单字节符的,是没有问题的,但如果当中包含了中文,编译器就会出现误读。在这种情况下,Qt Creator编辑器是正常的,对于MSVC编译器来说,源代码就会识别成下图的样子:
编译器识别乱码
这是使用EverEdit指定本地编码重读后的结果,文中的中文字符已经成乱码了,末端的引号也不见了。
      在UTF-8中,一个中文字符(包含中文标点符号)占用3个字节,“你好中文!”就占用了15个字节,而在GB2312中,占用2个字节,当MSVC把utf-8的编码的15字节上加上一个字节的英文引号合成16字节当成8个中文字符来处理,在MSVC在这一行末尾换行符出现前都没有找到下一个引号,它就以为是字符串在这里被敲了回车换行了,于是报警:“常量中有换行符”,并由此引出一系列的编译问题。不过,当无BOM的utf-8编码的字符串正好凑够偶数个字节时(偶数个汉字,奇数个汉字加奇数个英文字母),编译器通常不会报警,因为它认为用GB2312编码读出的字符是正常的。
     
 3 不管源文件是何种编码,只要MSVC能够正确识别,就可以通过编译。但MSVC的执行字符集默认也是本地字符集,对于程序员来说,它生成的可执行文件中的中文字符是GB2312编码的,而生成的Qt程序是utf-8编码来识别GB2312编码的文字,对于“你好中文!”这五个字符,采用GB2312编码后再以utf-8编码来读取,就会变成如下的乱码:
 utf-8编码读取GB2312编码乱码
 有一种走运的情况:当无BOM的UTF-8编码的字符串正好凑够偶数个字节时,反而不会出现乱码,因为编译器用GB2312编码读出来的乱码本身就是utf-8的编码,现在又是用utf-89解读,自然也就显示正常了。
 

怎么解决:中文乱码的解决方法

知道了乱码怎么产生的,那么解决就有思路了。
1.1 在Qt Creator中打开项目,点击左侧工具栏“项目”,在“编辑器”选项卡中把“默认编码”修改成“GB2312”。如下图:
修改默认编码
1.2 Qt自身跨平台的能力很强,选择了本地字符集,基本上也就跟跨平台说你是好人了,因为本地字符集跨平台时很麻烦,而utf-8对于跨平台就非常合适了,所以建议把代码换成utf-8编码吧,不然你用Qt Creator来开发,不如直接在VS上开发,岂不更好。
    所以第二种解决方法就是把项目中的所有文件全都换成utf-8+BOM编码保存。

2 解决了第一个问题,第二个问题基本也就不存在了,但有一种情况就是你拷贝的是别人的代码,当中可能包含着特殊的字符,编译时还是会出一样的警告和错误,那么就只能把原来的中文字符删除在当前的编辑器中重新输入一遍中文字符吧,有时候不偷懒才是真正的偷懒。

3 其实很多人,遇到的问题都集中在第三个,那么应该怎么解决了,在这里QString类中的fromLocal8Bit()函数家族就大有用武之地了。如:

QString str = “我就是中文”;

修改为:

QString str = QStringLiteral(“我就是中文”);

或者:

QString str = QString::fromLocal8Bit(“我就是中文”);

不过通过方法解决,就无法使用Qt的tr()方法来创建翻译了。你以为就这样结束了?怎么能够。这个解决的方法弊端非常明显,所以俺推荐各位小伙伴使用下面这种方法:
在使用到中文字符的头文件和源文件开关加上MSVC的一个宏(VS2010必须把VS2010sp1补丁包给打上,不然这个宏不起作用):

#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif

这个宏告诉MSVC,执行字符集是utf-8编码的,别乱搞成GB2312,还有一个好处就是可以正常使用tr()来包裹中文,方便翻译。效果如下
中文字符正常
Qt4写的代码用QTextCodec::codecForTr()来解决中文输入问题,为了防止错误的滥用,在Qt5中已经取消了这个方法。

小结一下中心思想 :
 1 Qt 4.7+VS2008 解决乱码: 

#include <QApplication>
#include <QTextCodec>  

int main(int argc, char *argv[])  
{  
   QApplication a(argc, argv);  

    // 以下部分解决中文乱码  
    QTextCodec *codec = QTextCodec::codecForName("GBK");  
    QTextCodec::setCodecForTr(codec);  
    QTextCodec::setCodecForLocale(codec);  
    QTextCodec::setCodecForCStrings(codec); 
}

Qt默认支持 VS2010/MinGW/Gcc 等编译器,而它们现在都已经真正支持UTF8了。当然,VS2010 对UTF8的支持会入侵代码(#pragma execution_character_set(“utf-8”))。 看看Qt官方论坛别人是怎么说的:   

Nothing special need to do, it will works by default.
If the exec-charset of your your compiler is UTF-8.

简单的说,从Qt5开始,源代码就是默认UTF8编码的。
当然,VC2010编辑器对带BOM的UTF8也是认识,只可惜VC2010编译器根本承认它是UTF8!
在继续看官方论坛的回复:
You can write a simple example like this

#include <QApplication>  
#include <QLabel>  

#if _MSC_VER >= 1600  
#pragma execution_character_set("utf-8")  
#endif  

int main(int argc, char *argv[])  
{  
      QApplication a(argc, argv);  
      QLabel label("???ó??ń??");  
      label.show();  

      return a.exec();  
  }  

If other people can reproduce your problem, you can file a bug.
较完整的解决方案(增加了Qt4/Qt5和非VC环境的判断):

// Coding: UTF-8(BOM)  
#if defined(_MSC_VER) && (_MSC_VER >= 1600)  
# pragma execution_character_set("utf-8")  
#endif  

#include <QApplication>  
#include <QTextCodec>  
#include <QLabel>  

int main(int argc, char* argv[])  
{  
    QApplication app(argc, argv);  

   #if QT_VERSION < QT_VERSION_CHECK(5,0,0)  
        #if defined(_MSC_VER) && (_MSC_VER < 1600)  
                QTextCodec::setCodecForTr(QTextCodec::codecForName("GB18030-0"));  
        #else  
                QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));  
        #endif  
   #endif  

    QLabel *label = new QLabel(QObject::tr("你好!"));  
    label->show();  

    return app.exec();  
}   

另外:Qt4/Qt5/Linux: 只要是默认的UTF8环境, 应该都没问题

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值