VC2010下Qt5的中文乱码问题

要搞清楚这个问题,先要弄明白编码。但是编码问题实在太复杂,这里肯定讲不开。

我先找一个例子,比如:“中文” 的 Unicode 码点/UTF8编码/GBK 分别是多少。

先去这个网站,输入 “中文” 查询对应的 Unicode 码点/UTF8编码: 
http://www.mytju.com/classcode/tools/encode_utf8.asp

Unicode的码点分别是(十进制):中(20013),文(25991)。 
对应的UTF8编码分别(16进制): 中(E4B8AD),文(E69687)。

然后再去下面这个网站,输入 “中文” 查询对应的 GBK 编码: 
http://www.mytju.com/classcode/tools/encode_gb2312.asp

GBK编码16进制(GBK内码)分别是:中(D6D0),文(CEC4)。

现在已经知道了"中文"的UTF8和GBK编码的具体值。 
我们再看看VC2010是怎么处理的。

1. 先看 无 BOM 的 UTF8 编码的代码 (utf8_no_bom.cpp)

01// utf8 no bom
02// 文件中包含不能在当前代码页(936)中表示的字符
03#include <stdio.h>
04 
05int main() {
06    const char* str = "中文";
07    for(int i = 0; i < sizeof(str); ++i) {
08        printf("0x%x ", str[i]&0xFF);
09    }
10    return 0;
11    // Output:
12    // 0xe4 0xb8 0xad 0xe6
13}

输出是:0xe4 0xb8 0xad 0xe6。 
感觉好像是对的。

但是,先别急:VC编译时输出了一条警告信息: 
utf8_no_bom.cpp : warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。 
请将该文件保存为 Unicode 格式以防止数据丢失。

潜台词就是,你这个代码有GBK不能表示的字符,请用Unicode方式保存。 
VC根本就没把 代码(utf8_no_bom.cpp) 当作UTF8,VC只是把它作为GBK处理罢了。

那为什么又输出了正确的结果呢?

因为 VC 把 (utf8_no_bom.cpp) 当作 GBK,而编译时也要转换为本地编码(也是GBK)。 
因此,UTF8编码的 “中文”,被VC当作编码为 “0xe4 0xb8 0xad 0xe6” 的其他中文处理了。 
VC已经不知道 “0xe4 0xb8 0xad 0xe6” 是对应 “中文” 字面值了。

但是在GBK(实际是无BOM的UTF8)转GBK的过程中,发现了一些UTF8编码的字符并不是 
GBK能表达的合理方式,因此就出现了那个C4819编译警告。

2. 再看带BOM的UTF8是怎么处理的 (utf8_with_bom.cpp)

01// utf8 with bom
02#include <stdio.h>
03 
04int main() {
05    const char* str = "中文";
06    for(int i = 0; i < sizeof(str); ++i) {
07        printf("0x%x ", str[i]&0xFF);
08    }
09    return 0;
10    // Output:
11    // 0xd6 0xd0 0xce 0xc4
12}

编译没有警告,但是输出有问题:0xd6 0xd0 0xce 0xc4。

源文件明明是 UTF8 编码的格式"0xe4 0xb8 0xad 0xe6”, 
怎么变成了 “0xd6 0xd0 0xce 0xc4” (这个是GBK编码)?

这就是VC私下干的好事:它自作聪明的将UTF8源代码转换为GBK处理了!

VC为何要做这样蠢事?

原因是为了兼容老的VC版本。 
因为以前的VC不能处理UTF8,都是用本地编码处理的。

3. 在看看真的GBK是怎么处理的 (gbk.cpp)

01// gbk
02#include <stdio.h>
03 
04int main() {
05    const char* str = "中文";
06    for(int i = 0; i < sizeof(str); ++i) {
07        printf("0x%x ", str[i]&0xFF);
08    }
09    return 0;
10    // Output:
11    // 0xd6 0xd0 0xce 0xc4
12}

没有编译错误,输出也和源代码一致:“0xd6 0xd0 0xce 0xc4”。

因为源文件就是GBK,cl在编译时GBK转化为GBK,没有改变字符串。

只是,现在很多人不想用GBK了(因为只能在中国地区用,不能表示全球字符)。

到这里,可以初步小结一下:

  1. VC编辑器和VC编译器是2个概念,VC编辑器支持UTF8并不能表示VC编译器也支持UTF8
  2. VC编辑器从2008?开始支持带BOM的UTF8(不带BOM的暂时没戏,因为会本地编码冲突)
  3. VC编译器从2010开始重要可以支持UTF8了(虽然支持方式很不优雅)

4. 看看VC2010是怎么处理带BOM的UTF8的 (utf8_with_bom_2010.cpp)

VC2010重要增加了UTF8的编译支持(#pragma execution_character_set("utf-8")), 
具体查看:

http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/2f328917-4e99-40be-adfa-35cc17c9cdec

01// utf8 with bom (VC2010), 这句是重点!
02#pragma execution_character_set("utf-8")
03 
04#include <stdio.h>
05 
06int main() {
07    const char* str = "中文";
08    for(int i = 0; i < sizeof(str); ++i) {
09        printf("0x%x ", str[i]&0xFF);
10    }
11    return 0;
12    // Output:
13    // 0xe4 0xb8 0xad 0xe6
14}

没有编译错误,输出也和源代码一致:“0xe4 0xb8 0xad 0xe6”。

UTF8编码,UTF8输出。完美!

回到 Qt5 的中文输出问题。

Qt默认支持 VS2010/MinGW/Gcc 等编译器,而它们现在都已经真正支持UTF8了。

当然,VS2010 对UTF8的支持会入侵代码(#pragma execution_character_set("utf-8"))。

看看Qt官方论坛别人是怎么说的: 
http://qt-project.org/forums/viewthread/17617

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

01#include <QApplication>
02  #include <QLabel>
03 
04  #if _MSC_VER >= 1600
05  #pragma execution_character_set("utf-8")
06  #endif
07 
08  int main(int argc, char *argv[])
09  {
10      QApplication a(argc, argv);
11      QLabel label("ąśćółęńżź");
12      label.show();
13 
14      return a.exec();
15  }

If other people can reproduce your problem, you can file a bug.

教完整的解决方案(增加了Qt4/Qt5和非VC环境的判断):

01// Coding: UTF-8(BOM)
02#if defined(_MSC_VER) && (_MSC_VER >= 1600)
03# pragma execution_character_set("utf-8")
04#endif
05 
06#include <QApplication>
07#include <QTextCodec>
08#include <QLabel>
09 
10int main(int argc, char* argv[])
11{
12    QApplication app(argc, argv);
13 
14#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
15#if defined(_MSC_VER) && (_MSC_VER < 1600)
16    QTextCodec::setCodecForTr(QTextCodec::codecForName("GB18030-0"));
17#else
18    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
19#endif
20#endif
21 
22    QLabel *label = new QLabel(QObject::tr("你好!"));
23    label->show();
24 
25    return app.exec();
26}

有以下几种类型(源代码必须是带BOM的UTF8):

  • Qt5+/VC2010+: 包含了 # pragma execution_character_set("utf-8") 已经支持中文
  • Qt5/VC2008-: 这个暂时误解(我还没找到方法)
  • Qt4+/VC2008-: 采用以前老的方式, 指定代码为 “GB18030-0” 编码
  • Qt4/Qt5/Linux: 只要是默认的UTF8环境, 应该都没问题

其实这个问题不是Qt特有的, 追根溯源还是C/C++和编译器的问题.

即使是支持UTF16的Java也同样难逃此问题.

不过还好, Go语言 算是彻底了解决了这个问题. 
以后转向 Go语言 了 !

 

转自开源中国 http://my.oschina.net/chai2010/blog/119833

我在电脑上找了一个显示中文.ttf文件加到了QtSDk->Simulator->Application->fonts中就可以解决了

转载于:https://www.cnblogs.com/Bonker/p/3453862.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/259089.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Tomcat 的 DefaultServlet

问题描述&#xff1a; 群里有人测试 Spring MVC&#xff0c;没有配置任何Controller&#xff0c;只配置了一个view resolver&#xff0c;指定了前缀后缀。 然后&#xff0c;他问的是 当访问 localhost:8080/test 的时候&#xff0c;为什么会被重定向到 localhost:8080/test/ &a…

Python学习(七)面向对象 ——封装

Python 类的封装 承接上一节&#xff0c;学了Student类的定义及实例化&#xff0c;每个实例都拥有各自的name和score。现在若需要打印一个学生的成绩&#xff0c;可定义函数 print_score() 该函数为类外的函数&#xff0c;如下&#xff1a; 1 class Student(object):2 def …

spss练习数据_SPSS篇——如何在成千上百万个数据中标识重复个案

本文就带大家来学习一个小技巧&#xff0c;如何运用SPSS标识重复个案。我们都知道在Excel中&#xff0c;通常会用到“筛选”功能来选出指定条件相同的单元格。那么在SPSS中&#xff0c;如何在成千上百万个数据中筛选出重复的个案呢&#xff1f; 小编就是要告诉你&#xff0c;几…

DOxygen for C++使用说明——Markdown支持

自Doxygen 版本1.8.0&#xff0c;Markdown被引进。 接下来&#xff0c;我们将先简单介绍标准的Markdown语法&#xff0c;读者可以进入Markdown官网查询更详细的细节。然后讨论一下Doxygen支持的Markdown扩展&#xff0c;最后讨论一下Doxygen对Markdown标准的实现细节。 Stand…

方程式漏洞之复现window2008/win7 远程命令执行漏洞

前几天就想写的&#xff0c;因为一些缘故就没写。此次是在外网环境下进行的。大家在内网中也一个样。 方法&#xff1a; 使用Eternalblue模块&#xff0c;剑测是否有漏洞然后msf生成一个dll直接反弹shell. PS&#xff1a;win版本的不知道缘何生成出来的dll是0kb 我就在自己本地…

C++空类和string类

1. 空类 1.1 空类默认哪六个成员函数。 1 class Empty2 {3 public:4 Empty(); //缺省构造函数 Empty e;5 Empty( const Empty& ); //拷贝构造函数 Empty e2(e1);6 ~Empty(); //析构函数7 Empty& operator( const Empty& ); //赋值运算符…

客服会话 小程序 如何发起_小程序、公众号、App三者如何融合布局?这里有一份避坑指南...

对产品经理来说&#xff0c;小程序无疑是2020年最火爆的词之一了。我们能看到&#xff0c;就在今年疫情期间&#xff0c;小程序DAU达到4.5亿&#xff0c;而超市、生鲜果蔬、社区购物等都同比增长100个点左右&#xff0c;小程序的商业价值很明显地在快速释放。小程序如此火爆&am…

DOxygen for C++使用说明——注释代码二

这一次我在谷歌搜索中检索到了Doxygen在github的仓库&#xff0c;进去一看&#xff0c;令人大喜&#xff0c;github仓库里含有了一个Doxygen的官方配置文件Doxyfile,于是下载下来&#xff0c;发现Doxyfile已经配置了将仓库中的\src文件编译成Documentation,并且将结果放在了dox…

python super()(转载)

一、问题的发现与提出 在Python类的方法&#xff08;method&#xff09;中&#xff0c;要调用父类的某个方法&#xff0c;在Python 2.2以前&#xff0c;通常的写法如代码段1&#xff1a; 代码段1&#xff1a; class A:def __init__(self):print "enter A"print "…

Swagger+Spring mvc生成Restful接口文档

2019独角兽企业重金招聘Python工程师标准>>> Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法&#xff0c;参数和模型紧密集成到服务器端…

JavaScript——变量与基本数据类型

前言 JavaScript中的变量为松散类型&#xff0c;所谓松散类型就是指当一个变量被申明出来就可以保存任意类型的值&#xff0c;就是不像SQL一样申明某个键值为int就只能保存整型数值&#xff0c;申明varchar只能保存字符串。一个变量所保存值的类型也可以改变&#xff0c;这在Ja…

vscode可以打开jupyternotebook吗_刚刚,官方宣布 VS Code 支持 Python 全开发了!

关注Python高校每天早上23:10准时推送北京时间 2019 年 9 月 21 日&#xff0c;PyCon China 2019 在上海举行。在下午的演讲中&#xff0c;来自微软开发工具事业部的资深研发工程师韩骏做了主题为《Python 与 Visual Studio Code 在人工智能应用中的最佳 Azure 实践》的演讲。在…

C++类的内联成员函数应放在哪

今天复习C Primer的时候&#xff0c;看到了关于C类的内联成员函数的放置&#xff0c;应该放在头文件中。那么这到底是为什么 呢&#xff1f;仅仅是一种代码规范问题还是必须这样做呢&#xff1f; 下面我就来讲讲我自己的理解吧。要彻底理解这个问题&#xff0c;首先就要了解下函…

python selenium自动化(三)Chrome Webdriver的兼容

当一个自动化测试被实现在一个浏览器之后&#xff0c;我们会希望我们的测试能够覆盖到尽量多的别的浏览器。通过跨平台的测试来保证我们的程序在多个浏览器下都能正常工作。 在安装了selenium之后&#xff0c;firefox webdriver和IE webdriver就已经是ready to use的了&#xf…

NDK 编译armebai-v7a的非4字节对齐crash Fatal signal 7 (SIGSEGV) 错误解决

一直都是编译armabi的。没有不论什么问题&#xff0c;这个架构是软件模拟浮点运算的。后来看到NDK文档上说armabi-v7a是针对有硬件处理浮点计算的arm cpu的。 于是就改动配置编译armebai-v7a的so文件。 结果是编译没问题。一执行就是crash掉&#xff0c;Fatal signal 7 (SIGSEG…

作业三

作业三 第一章问题&#xff1a;书上写的“Bug的多少可以直接衡量一个软件的开发效率、用户满意度、可靠性和可维护性”&#xff0c;那么一个比较完好的软件中一般大概会出现多少Bug? 第二章问题&#xff1a;现在开始训练写更多的程序能否更早地达到软件工程师的标准&#xff1…

springboot默认数据源如何设置连接数_Spring Boot系列之配置数据库连接池

在实际的应用开发中&#xff0c;与数据库交互通常使用数据库连接池来重用Connection对象&#xff0c;减少资源消耗。Spring Boot 的数据源是自动配置的。在 Spring Boot 2.2.1 版本中&#xff0c;有几种数据源配置可选&#xff0c;它们按照 HikariCP -> Tomcat -> DBCP2 …

使用Qt正则表达式提取全路径的文件名

问题描述&#xff1a; 给定三个全路径&#xff0c;例如 path1"C:/Users/asus/Desktop/nefertiti_4465.obj"; path2"C:/Users/asus/Desktop/nefertiti_4465_k1.txt"; path3"C:/Users/asus/Desktop/nefertiti_4465_k2.txt"; 我希望说明path2和pa…

Beyond Compare 3.3.8 build 16340 + Key

本文摘录自冰点社区&#xff1a;http://forum.z27315.com/topic/14746-beyond-compare-338-build-16340-key/ Download Beyond Compare 3 Current Version: 3.3.8, build 16340, released June 19, 2013 Windows 版本 Windows Standard and Pro EditionsEnglish version 5800k…

hdu 1198 Farm Irrigation

题目链接&#xff1a; http://acm.hdu.edu.cn/showproblem.php?pid1198 题目大意&#xff1a; 有一大块土地需要浇水&#xff0c;这块土地由很多的小块土地&#xff08;有十一种&#xff09;组成&#xff0c;小块土地上有水沟&#xff0c;问至少需要建几个井&#xff0c;才能灌…