彻底解决Qt中文乱码以及汉字编码的问题(UTF-8/GBK)

彻底解决Qt中文乱码以及汉字编码的问题(UTF-8/GBK)一、Qt环境设置QtCreator,菜单->工具->选项->文本编辑器->行为->文件编码:默认编码:System(简体中文windows系统默认指的是GBK编码,即下拉框选项里的GBK/windows-936-2000/CP936/MS936/windows-936)二、编码知识科普Qt常见的两种编码是:UTF-8和GBK★UTF-8:UnicodeTransformat

大家好,又见面了,我是你们的朋友全栈君。

尊重作者,支持原创,如需转载,请附上原地址:https://blog.csdn.net/libaineu2004/article/details/19245205

这篇文章有点长,内容有点多,如果时间急迫,可以直接翻页去末尾看结论。红色字体加粗的。(#^.^#)

 

一、Qt Creator环境设置

1、cpp或h文件从window上传到Ubuntu后会显示乱码,原因是因为ubuntu环境设置默认是utf-8,Windows默认都是GBK.

我们使用的Windows系统本地字符集编码为GBK。

2、Windows环境下,Qt Creator,菜单->工具->选项->文本编辑器->行为->文件编码->默认编码,常用的选项有以下几个:

System(简体中文windows系统默认指的是GBK编码)

GBK/windows-936-2000/CP936/MS936/windows-936

UTF-8

 

二、编码知识科普

Qt常见的两种编码是:UTF-8和GBK
★UTF-8:Unicode TransformationFormat-8bit,允许含BOM,但通常不含BOM。是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24为(三个字节)来编码。UTF-8包含全世界所有国家需要用到的字符,是国际编码,通用性强。UTF-8编码的文字可以在各国支持UTF8字符集的浏览器上显示。如果是UTF8编码,则在外国人的英文IE上也能显示中文,他们无需下载IE的中文语言支持包。
★GBK是国家标准GB2312基础上扩容后兼容GB2312的标准。GBK的文字编码是用双字节来表示的,即不论中、英文字符均使用双字节来表示,为了区分中文,将其最高位都设定成1。GBK包含全部中文字符,是国家编码,通用性比UTF8差,不过UTF8占用的数据库比GBD大。GBK是GB2312的扩展,除了兼容GB2312外,它还能显示繁体中文,还有日文的假名。
★GBK、GB2312等与UTF8之间都必须通过Unicode编码才能相互转换:
GBK、GB2312--Unicode--UTF8
UTF8--Unicode--GBK、GB2312
★在简体中文windows系统下,ANSI编码代表GBK/GB2312编码,ANSI通常使用0x80~0xFF范围的2个字节来表示1个中文字符。0x00~0x7F之间的字符,依旧是1个字节代表1个字符。Unicode(UTF-16)编码则所有字符都用2个字节表示。

 

三、编码转换

Windows自带的记事本,无法查看UTF-8编码的文件到底有无BOM,需要使用其他文件编辑器,比如EditPlus或者SublimeText。
UTF-8与ANSI(即GBK)的互转,可以使用EditPlus工具”文件另存为”或者Encodersoft编码转换工具对.cpp和.h源文件文本进行批量转换.

 

四、QString显示中文乱码的原因

我们使用的Windows系统本地字符编码(Local字符集)为GBK。编译器分析出源文件字符编码之后,会进行解码再编码,将源字符集转码成执行字符集。执行字符集一般默认为使用本地字符编码(Local字符集)。

Qt5可以设置Local字符集,GBK/UTF-8

QTextCodec *codec = QTextCodec::codecForName("UTF-8");//或者"GBK",不分大小写
QTextCodec::setCodecForLocale(codec);

Qt5中QString内部采用unicode字符集,utf-16编码。构造函数QString::QString(const char *str)默认使用fromUtf8(),将str所指的执行字符集从utf-8转码成utf-16。
由上面fromUtf8()可知,QString需要执行字符集编码为utf-8,然后以utf-8进行解码,再编码为utf-16才能获得正确的字符编码。显示中文乱码的原因其实就是QString转码方式与执行字符集不一致。(比如,源字符集为本地字符集GBK编码,QString以utf-8的方式进行解码,会导致获得错误的二进制编码,再将错误二进制转为utf-16就会出现乱码。)
 

五、Qt编码指定

Qt需要在main()函数指定使用的字符编码:

#include <QTextCodec>

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

    //设置中文字体  
    a.setFont(QFont("Microsoft Yahei", 9));

    //设置中文编码
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
    QTextCodec *codec = QTextCodec::codecForName("GBK");
#else
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");
#endif
    QTextCodec::setCodecForLocale(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForTr(codec);
#else
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForLocale(codec);
#endif

    return a.exec();
}

这里只列举大家最常用的3个编译器(微软VC++的cl编译器,Mingw中的g++,Linux下的g++),源代码分别采用GBK和无BOM的UTF-8以及有BOM的UTF-8这3种编码进行保存,发生的现象如下表所示。

情况1:指的是Local字符集为GBK

情况2:指的是Local字符集为UTF-8

  • 源代码的编码

    编译器

    显示正常

    显示乱码

    GBK

    win vs cl

    情况1

    情况2

    win mingw-g++

    情况1

    情况2

    linux g++

    情况1

    情况2

    UTF-8(无BOM)

    win vs cl

    编译失败

    error C2001: 常量中有换行符

    编译失败
    error C2001: 常量中有换行符

    win mingw-g++

    情况2

    情况1

    linux g++

    情况2

    情况1

    UTF-8(有BOM)

    win vs cl

    情况1

    情况2(有#pragma预处理)

    情况2(没有#pragma预处理)

    win mingw-g++

    情况2

    情况1

    linux g++

    情况2

    情况1
  • 如果您使用的是Visual C++编译器,则默认情况下不会将您的源代码视为utf-8编码。除非有BOM,否则它将使用您当前的代码页进行解释。就是说,当使用Visual C++编译程序的时候,它会分析源文件采用何种编码,有BOM标识符则可以正确识别其编码是UTF-8,若没有BOM标识符则认为其使用本地字符集编码(Local字符集)。Local字符集是什么?取决于你的设置QTextCodec *codec = QTextCodec::codecForName(???);
  • 如果源文件是UTF-8+BOM的编码方式,还需要在头文件加入
#if defined(_MSC_VER) && (_MSC_VER >= 1600)    
# pragma execution_character_set("utf-8")    
#endif

或者添加QMAKE_CXXFLAGS += /utf-8到您的.pro文件中。

  • 如果源文件是UTF-8+无BOM的编码方式,则一定不能加#pragma execution_character_set(“utf-8”),不然会产生乱码。

 

六、测试案例

案例1、中文字符串测试

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

#include <QApplication>
#include <QTextCodec>
#include <QPushButton>
#include <QDebug>
#include <QString>

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

    //设置中文字体  
    a.setFont(QFont("Microsoft Yahei", 9));

    //设置中文编码
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
    QTextCodec *codec = QTextCodec::codecForName("gbk");
#else
    QTextCodec *codec = QTextCodec::codecForName("utf-8");
#endif
    QTextCodec::setCodecForLocale(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForTr(codec);
#else
    QTextCodec *codec = QTextCodec::codecForName("utf-8");
    QTextCodec::setCodecForLocale(codec);
#endif

    QString str(QObject::tr("1中文"));
    qDebug() << str;
    qDebug() << QStringLiteral("2中文");
    qDebug() << QString::fromLatin1("3中文");
    qDebug() << QString::fromLocal8Bit("4中文");
    qDebug() << QString::fromUtf8("5中文");
    qDebug() << QString::fromWCharArray(L"6中文");

    return a.exec();
}

当QTextCodec::codecForName(“utf-8”);时,

QString::fromLocal8Bit和QString::fromUtf8是等效的。

当QTextCodec::codecForName(“gbk”);时,

QString::fromLocal8Bit和QString::fromUtf8是不等效的。

案例2、QCom跨平台串口调试助手(http://www.qter.org/?page_id=203)
源代码qcom\mainwindow.cpp,aboutdialog.cpp等文件用的是UTF-8编码(无BOM);但是qcom\qextserial\*.*文件用的是ANSI编码.在linux环境编译完全OK.
笔者Windows环境的Qt Creator+微软VC++编译器,环境设置用的是ANSI(即GBK)编码.编译源文件会报错.
错误提示”fatal error C1018: 意外的 #elif”.

彻底解决Qt中文乱码以及汉字编码的问题(UTF-8/GBK)
解决方法由两种:

方法1:

彻底解决Qt中文乱码以及汉字编码的问题(UTF-8/GBK)

把qcom\的所有cpp和h文件都用工具转换成ANSI编码,main()函数使用QTextCodec::setCodecForTr(QTextCodec::codecForName(“GBK”));

方法2:

先把Qt Creator环境设置用的是UTF-8编码,

彻底解决Qt中文乱码以及汉字编码的问题(UTF-8/GBK)

再把qcom\的所有cpp和h文件都用工具转换成UTF-8+BOM编码,请注意,如果文件转换成UTF-8(无BOM),编译仍会失败.main()函数使用QTextCodec::setCodecForTr(QTextCodec::codecForName(“GBK”));//注意,此处仍是”GBK”,不是”UTF-8″
重新编译,OK!

其它:

 

七、结论

Windows环境下,Qt Creator+微软VC++编译器,新建工程,

1、如果该工程不需要跨平台使用(只在win),那么工程设置请使用GBK的编码方式.

2、如果该工程要跨平台使用(win+linux),那么工程设置请使用UTF-8+BOM的编码方式.

彻底解决Qt中文乱码以及汉字编码的问题(UTF-8/GBK)

另外,还需要在预编译头文件加入

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

或者添加QMAKE_CXXFLAGS += /utf-8到您的.pro文件中。

3、Linux环境下,Qt Creator+gcc,新建工程,

没有GBK编码可选,默认是UTF-8(无BOM)编码方式,考虑到跨平台,建议选择UTF-8+BOM的编码方式.

 

★★★★★★★★★★★★★★★综上所述,解决乱码的方法概括如下:★★★★★★★★★★★★★★★★★★★★★

1、如果IDE是Qt Creator,把它的环境设置为“UTF-8+BOM”编码。

2、如果IDE是Visual Studio,请下载插件,名称是ForceUTF8 (with BOM),所有源文件和头文件都会保存为“UTF-8+BOM”编码。

3、如果编译器是MSVC,请在预编译头stdafx.h文件加入

#if defined(_MSC_VER) && (_MSC_VER >= 1600)    
# pragma execution_character_set(“utf-8”)    
#endif

4、源码文件main函数入口设置中文编码:

    #include <QTextCodec>

    QApplication a(argc, argv);

    //设置中文字体  
    a.setFont(QFont(“Microsoft Yahei”, 9));

//设置中文编码
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
    QTextCodec *codec = QTextCodec::codecForName(“gbk”);
#else
    QTextCodec *codec = QTextCodec::codecForName(“utf-8”);
#endif
    QTextCodec::setCodecForLocale(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForTr(codec);
#else
    QTextCodec *codec = QTextCodec::codecForName(“utf-8”);
    QTextCodec::setCodecForLocale(codec);
#endif

5、如此一来,不管是MSVC编译器还是MinGW编译器,都能编译通过,且支持中文!

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

 

x、参考文献

Qt官网文档 

https://wiki.qt.io/Strings_and_encodings_in_Qt

https://doc.qt.io/qt-5/unicode.html

ASCII,Unicode和UTF-8完全搞清楚 https://blog.csdn.net/Deft_MKJing/article/details/79460485

Qt中文乱码原因及解决方案 https://blog.csdn.net/qq_35905572/article/details/95042444

Qt中文乱码问题 http://blog.csdn.net/brave_heart_lxl/article/details/7186631

尊重作者,支持原创,如需转载,请附上原地址:https://blog.csdn.net/libaineu2004/article/details/19245205

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/130422.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 手机上有哪些不错的c语言编程软件?[通俗易懂]

    手机上有哪些不错的c语言编程软件?[通俗易懂]手机上编程C语言的软件其实非常多,下面我介绍2个不错的软件,分别是C语言编译器和C++编译器,这2个软件都可以在手机上直接编译运行C语言程序,而且使用起来非常不错,下面我简单介绍一下这2个软件的安装和使用:C语言编译器1.首先,下载安装C语言编译器,这个可以直接到手机应用商店中搜索,如下,大概也就13兆左右:2.安装完成后,打卡这个软件,就可以直接新建C语言文件,进…

    2025年9月6日
    4
  • 手机号码归属地数据库下载

    手机号码归属地数据库下载一份手机号归属地数据,共有174495条数据,包括中国移动,中国联通,中国电信的(包含152、186、188、189开头的手机号)。其中cardtype字段基本上没有什么用。因为可以通过办理某些业务就可以把如全球通卡转成神州行卡。对于这样的一份数据,你想要怎么利用?如果你只是想做一个手机号归属地查询的功能,那就浪费了。这个收数据库的主要功能就是通过手机号的前7位数字判断出手机号的归属城…

    2022年7月22日
    48
  • 品优购-day01笔记-代码规范&品优购项目准备工作&首页初步

    品优购-day01笔记-代码规范&品优购项目准备工作&首页初步typora-copy-images-to:media第01阶段.WEB基础:品优购-day01笔记-代码规范&品优购项目准备工作&首页初步学习目标能会引入ico图标能简单看懂网站优化的三大标签能使用字体图标(重点)能说出我们css属性书写顺序能跟上pink老师的节奏完成品优购项目一、代码规范(重点)1.概述欢迎使用品优购代码规范,这是借鉴…

    2022年5月28日
    33
  • sql的隐式转换_js强制转换和隐式转换

    sql的隐式转换_js强制转换和隐式转换什么叫做隐式转换? 显示转换,就是你使用转换函数进行操作。隐式转换,就是你不使用转换函数,默认就给转换了。比如定义一个int型的变量@a,然后给变量符值set@a=’2’,这个就会隐式转换,把字符转换成数字了。Oracle隐式转换1     Oracle 隐式转换           Oracle中对不同类型的处理具有显式类型转换(Explicit)和隐式类型转换(Implicit…

    2022年10月11日
    4
  • Seajs使用实例入门

    Seajs使用实例入门1 在项目中引入 sea js 其中内容为 varBASEPATH TestSea function a b functionc a returnfuncti b return toString call b object a functiond returnA functione a if a about blank a wi

    2025年7月13日
    2
  • 通俗易懂–岭回归(L2)、lasso回归(L1)、ElasticNet讲解(算法+案例)

    通俗易懂–岭回归(L2)、lasso回归(L1)、ElasticNet讲解(算法+案例)

    2021年6月20日
    142

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号