Qt5中文编码问题解决办法

本文详细阐述了如何将Win10和Linux环境下基于Qt5.15.2的项目从Qt4.8编码转换为UTF-8,包括修改源文件编码、调整main函数及工程配置,以及处理不同开发工具和终端显示问题。重点讨论了编码转换对版本控制、代码比对和终端输出的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、开发环境

跨平台开发,开发环境为Windows和Linux。

1、Windows(Win10)

Qt:Qt5.15.2

IDE:Microsoft Visual Studio Professional 2019 版本 16.11.5

编译器:MSVC 19.29.30136 版,_MSC_VER为1929

2、Linux(Centos 7.6)

Qt:Qt5.15.2

IDE:Qt Creator 5.0.3

编译器:GCC 7.3.1

二、现有代码需要做的修改

VS2010+Qt4.8代码升级到VS2019+Qt5.15.2,针对乱码问题,需要做下面三方面的修改。

1、修改源文件的编码格式

所有的h、cpp文件修改为UTF-8 without BOM。

备注:可使用工具或脚本将原来已存在的cpp、h文件批量修改格式。VS安装Force UTF-8(No Bom)插件,之后新建的文件都会被自动保存为UTF8 without BOM格式。

2、修改mian函数

由原来的

QTextCodec *codec = QTextCodec::codecForName("GBK");

QTextCodec::setCodecForLocale(codec);

QTextCodec::setCodecForCStrings(codec);

QTextCodec::setCodecForTr(codec);

修改为:

QTextCodec* codec = QTextCodec::codecForName("utf-8");

QTextCodec::setCodecForLocale(codec);

3、修改工程配置

3.1、Visual Studio

属性--配置属性--c/c++--所有选项--附加选项--/utf-8。

备注:“/utf-8”等效于“/source-charset:utf-8”和“/execution-charset:utf-8”,会同时指定源码字符集、执行字符集为UTF-8。

3.2、Qt Creator

如果是Linux下的Qt Creator,使用的编译器是GCC,则不需要做任何修改,只要源码文件是UTF-8即可。

如果是Windows下的Qt Creator,使用MinGW时,也不会出问题,但如果使用MSVC,则需要在pro文件中增加如下内容:“msvc:QMAKE_CXXFLAGS += /source-charset:utf-8 /execution-charset:utf-8”或“msvc:QMAKE_CXXFLAGS += /utf-8”,否则会出现编译不通过或中文乱码的问题。

三、可能造成的影响

1、代码版本管理工具--svn

1.1、只修改编码

用源码中的xxx.cpp举例,文件编码是GB2312,如下图所示:

如果只修改文件编码格式为UTF8 without BOM,但不修改文件具体内容,使用svn提交时,会提示文件变化,双击打开该文件提示文件内容相同但编码格式不同,如下图所示: 

 

1.2、修改编码且修改内容

如果修改文件编码格式,同时修改了内容,使用svn提交时,会提示文件变化,双击打开该文件不会提示文件编码格式不同,只会显示修改了什么内容,如下图所示:

1.3、结论

将文件编码格式由GB2312修改为UFT-8 without BOM,仍然可以正常对比和原来代码的差异,影响不大。

2、代码比对工具--Total Commander

2.1、只修改编码

用源码中的xxx.cpp举例,文件编码是GB2312,如果只修改文件编码格式为UTF8 without BOM,不修改内容,使用Total Commander对比时,会提示文件变化,双击打开该文件看不到任何内容差异,如下图所示:

2.2、修改编码且修改内容

如果修改文件编码格式,同时修改了内容,使用Total Commander对比时,提示文件变化,双击打开该文件,能正确显示修改了什么内容,

2.3、结论

将文件编码格式由GB2312修改为UFT-8 without BOM,Total Commander仍然可以正常对比和原来代码的内容差异。

但仅修改编码格式,未修改内容的文件也会作为差异文件显示,没法一眼确定差异文件是否内容修改。

3、可忽略编码差异的代码比对工具--WinMerge

当我们把源文件批量修改为UTF-8且修改了源码内容之后,我们希望和旧的代码对比时,可以忽略编码差异,只显示内容有变化的文件。

在Total Commander中没有找到相关方法,使用WinMerge代码对比工具可实现该需求。

4、Win10终端显示问题

Win10的终端默认是GBK的编码,所以源码字符集和执行字符集都修改为UTF-8之后,运行程序会发现程序界面显示正常,但cmd窗口输出乱码,如下图所示:

解决办法有两种:

第一种:修改windows全局配置,会影响所有程序。影响较大,不建议。

控制面板--时钟和区域--区域--管理--更改系统区域设置--区域设置--Beta版:使用Unicode UTF-8提供全球语言支持。

第二种:在程序中设置windows运行环境下cmd窗口的编码,只在本次程序运行期间生效,不影响其他程序。代码如下:

 效果如下:

chcp是windows cmd中的命令,具体作用是更改活动控制台代码页,如果使用不带参数,chcp显示活动控制台代码页的数目。

65001是UTF-8代码页,chcp 65001是将cmd中的活动代码页修改为UTF-8。该命令只会影响自己所在的cmd窗口,不会影响同时打开的其他cmd窗口。设置活动代码页之后,一旦关闭cmd窗口将失效,再次打开还是系统默认的代码页。

四、乱码原因分析

先了解两个概念:

源码字符集(the source character set):源码文件是使用何种编码保存的。

执行字符集(the execution character set):可执行程序内保存的是何种编码(程序执行时内存中字符串编码)。

程序从编写到运行涉及三个编码格式:源文件代码保存的格式(源码字符集)、程序运行时加载到内存中的编码格式(执行字符集)、显示的编码格式(如ui显示、终端显示)。这三个格式中如果有一个格式不一致,就会导致乱码。

MSVC和GCC在默认处理编码字符集和执行字符集时有差异,导致相同的代码在不同编译器下可能会出现乱码。

只要在不同的编译器下,源码字符集、执行字符集都统一为UTF-8,就能解决乱码的问题。

1、MSVC

MSVC的编码字符集和执行字符集默认都是GBK,想把MSVC的编码字符集和执行字符集都修改为UTF-8,并不容易。

1.1、源码字符集

默认情况下,MSVC编译时,只有“UFT-8 with BOM”格式的文件会被认为是UTF-8,而“UTF-8 without BOM”和其他格式都会被认为是GBK。

对于MSVC2015以后的版本,如果源文件是UTF-8 without BOM,不是UFT-8 with BOM,还想让MSVC把源码当做UTF-8处理,可以专门告诉编译器源码文件是UTF-8格式,编译时增加命令“/source-charset:utf-8”。

对于MSVC2015之前的版本,这个命令不一定生效,源文件保存成UTF-8 without BOM格式就会出问题,需要注意。

1.2、执行字符集

默认情况下,MSVC在编译时,无论cpp文件源码字符集是UTF-8 without BOM、UTF-8 with BOM、GBK 中的哪一种,只要没有告诉编译器执行码字符集是UFT-8,则最终在内存中,都会被强制转换GBK处理。

想让MSVC执行字符集为UTF-8,必须对源文件增加执行字符集的声明或编译时增加命令。

声明的方式是在每个源码文件的开头增加该内容:#pragma execution_character_set("utf-8")。

编译时增加的命令是“/execution-charset:utf-8”。

1.3、结论

我们的最终目的是想让MSVC编译器的源码字符集和执行字符集都是UTF-8,但对于不同版本的MSVC编译器来说,要实现这一目的,方法并不相同,也没有一种方法能解决所有MSVC版本的编译器。

针对MSVC2019的版本,我们可以得出如下结论:

想让MSVC的编码字符集是UTF-8,要么把文件保存为UTF-8 with BOM,让它自己认为文件是UTF-8;要么文件保存为UTF-8 without BOM,通过编译时增加命令的方式让编译器知道文件是UTF-8的。

想让MSVC的执行字符集是UTF-8,则必须通过编译时增加命令的方式告诉编译器。

保存成UTF-8 with BOM,能适应更多版本的MSVC编译器,但对MSVC2019来说,保存成UTF-8 without BOM就可以,而且文件保存成UTF-8 without BOM或UTF-8 with BOM,对代码影响都不大,随时可以使用工具批量修改,不会带来太多的工作量。

参考Qt5.15.2带的例子,源码都是UTF-8 without BOM格式,因此在MSVC2019下,推荐源码保存为UTF-8 without BOM格式,编译时指定参数“/utf-8”。

2、GCC

GCC编码字符集和执行字符集默认都是UTF-8。

对于GCC来说,只要源码文件保存成UTF-8即可(带或不带BOM均可)。

五、notepad批量转UTF8

从网上找了多个编码转换工具,自己也尝试写、从网上找python脚本,对文件进行批量转换,但转换结果都不理想,大部分文件都可以正常转换成UTF8,但少量文件转换后可能出现中文乱码的情况。

经过多次尝试,发现使用notepad++程序进行编码转换,可以保证文件不乱码的情况下将文件转换为UTF8。

Notepad++程序并未提供对外的编程接口,想控制该程序进行批量转换就需要使用其提供的Python Script插件,且只支持python2的写法。

经过探索之后,将notepad++程序进行打包,大家可以直接使用。使用步骤略微繁琐,需要大家按下面步骤进行使用。

1、解压文件

    将“Notepad++.zip”拷贝到某个位置,进行解压。

2、将语言修改为英文

双击解压出文件夹里的“notepad++.exe”程序,修改程序界面为英文。

3、打开脚本文件

    如果本机原来就安装了notepad程序,必须通过解压文件中打开的“notepad++.exe”去打开脚本文件,文件路径如下图所示:

4、手动修改要转换的文件路径

手动修改脚本中要处理的文件路径,如下图所示:

将该路径复制粘贴到脚本中即可(需要是r”...”的格式):

 

5、打开notepad中的python终端

 

 6、执行脚本

 

7、验证转换结果是否正确

使用“可忽略编码差异的代码比对工具--WinMerge”可以查看转换结果是否正确。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值