要搞清楚这个问题,先要弄明白编码。但是编码问题实在太复杂,这里肯定讲不开。
我先找一个例子,比如:“中文” 的 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)
02 |
// 文件中包含不能在当前代码页(936)中表示的字符 |
06 |
const char * str = "中文" ; |
07 |
for ( int i = 0 ; i < sizeof(str); ++i) { |
08 |
printf( "0x%x " , str[i]& 0xFF ); |
12 |
// 0xe4 0xb8 0xad 0xe6 |
输出是: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)
05 |
const char * str = "中文" ; |
06 |
for ( int i = 0 ; i < sizeof(str); ++i) { |
07 |
printf( "0x%x " , str[i]& 0xFF ); |
11 |
// 0xd6 0xd0 0xce 0xc4 |
编译没有警告,但是输出有问题: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)
05 |
const char * str = "中文" ; |
06 |
for ( int i = 0 ; i < sizeof(str); ++i) { |
07 |
printf( "0x%x " , str[i]& 0xFF ); |
11 |
// 0xd6 0xd0 0xce 0xc4 |
没有编译错误,输出也和源代码一致:“0xd6 0xd0 0xce 0xc4”。
因为源文件就是GBK,cl在编译时GBK转化为GBK,没有改变字符串。
只是,现在很多人不想用GBK了(因为只能在中国地区用,不能表示全球字符)。
到这里,可以初步小结一下:
- VC编辑器和VC编译器是2个概念,VC编辑器支持UTF8并不能表示VC编译器也支持UTF8
- VC编辑器从2008?开始支持带BOM的UTF8(不带BOM的暂时没戏,因为会本地编码冲突)
- 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" ) |
07 |
const char * str = "中文" ; |
08 |
for ( int i = 0 ; i < sizeof(str); ++i) { |
09 |
printf( "0x%x " , str[i]& 0xFF ); |
13 |
// 0xe4 0xb8 0xad 0xe6 |
没有编译错误,输出也和源代码一致:“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> |
05 |
#pragma execution_character_set( "utf-8" ) |
08 |
int main( int argc, char *argv[]) |
10 |
QApplication a(argc, argv); |
11 |
QLabel label( "ąśćółęńżź" ); |
If other people can reproduce your problem, you can file a bug.
教完整的解决方案(增加了Qt4/Qt5和非VC环境的判断):
02 |
# if defined(_MSC_VER) && (_MSC_VER >= 1600 ) |
03 |
# pragma execution_character_set( "utf-8" ) |
06 |
#include <QApplication> |
10 |
int main( int argc, char * argv[]) |
12 |
QApplication app(argc, argv); |
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" )); |
18 |
QTextCodec::setCodecForTr(QTextCodec::codecForName( "UTF-8" )); |
22 |
QLabel *label = new QLabel(QObject::tr( "你好!" )); |
有以下几种类型(源代码必须是带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中就可以解决了
- IE下get传中文乱码的问题 -- 解决方案 (js)
W3school 函数 JavaScript 全局对象 定义和用法 encodeURI() 函数可把字符串作为 URI 进行编码. 语法 encodeURI(URIstring) 参数 描述 URIs ...
- Linux 解决Linux下火狐浏览器中文乱码成方块显示问题
解决Linux下火狐浏览器中文乱码成方块显示问题 by:授客 QQ:1033553122 测试环境: CentOS-6.0-x86_64 问题描述: 浏览器页面显示如下 解决方法: 安装中文支 ...
- windows下git bash中文乱码解决办法
一.解决办法1:(直接上图) 1.在git bash下,右键 出现下图,选择options: 2.选择“Text” 3.将“Character set”设置为 UTF-8 转:windows下git ...
- [转]Git for windows 下vim解决中文乱码的有关问题
Git for windows 下vim解决中文乱码的问题 原文链接:Git for windows 下vim解决中文乱码的有关问题 1.右键打开Git bash: 2.cd ~ 3.vim .vim ...
- VS2013+QT5.3 中文乱码和中文路径不识别
http://blog.csdn.net/brave_heart_lxl/article/details/7186631 ubun图中文乱码 https://blog.csdn.net/u013007 ...
- 两种解决Qt5显示中文乱码的方法(使用QStringLiteral和#pragma execution_character_set("utf-8")两种方法)
升级到Qt5.X之后,原先解决的Qt显示中文乱码的方法突然不适用了,找了很多方式来解决这个问题第一种:在公司代码里看到的方法,先将对应的cpp文件用windows自带的记事本打开,另存为UTF-8格式 ...
- Ubuntu环境下 matplotlib 图例中文乱码
最近做了一个最小二乘法的代码编写并用 matplotlib 绘制了一张图,但是碰到了中文乱码问题.简单搜索之后,发现有人总结出了比较好的方案,亲测可行.推荐给大家. 本文前提条件是 已经 安装好 ma ...
- 解决windows下FileZilla server中文乱码问题
最利用cuteftppro FTP做文件夹同步,发现中文的文件夹及文件名都出现了乱码问题, 一开始以为是cuteftppro的问题,谷哥度娘找了一堆的解决方案都没有解决乱码问题,真是头疼啊! 后来终于 ...
- [oracle]解决centos 7下oracle的中文乱码问题
首先在形成中文乱码的原因是由于字符集不统一导致的,不同的字符集在转换的过程中必然要出现乱码,当然不排除可以转换.所以要解决中文乱码问题,思路是将输入.存储.显示等流程中涉及到字符集都统一为一种,对于o ...
随机推荐
- jdbc第三天
事务 什么是事务? 转账: 1. 给张三账户减1000元 2. 给李四账户加1000元 当给张三账户减1000元后,抛出了异常!这会怎么样呢?我相信从此之后,张三再也不敢转账了. 使用事务就可以处理这 ...
- NI License Activator 用法
双击打开后,看到这种界面,将白色方格通过鼠标右击点绿就能够了. NI <wbr>License <wbr>Activator <wbr>用法 可能会出现这样的情况, ...
- 解决Failure to transfer org.apache.maven.plugins:maven-surefire-plugin:pom:2.12.4
Failure to transfer org.apache.maven.plugins:maven-surefire-plugin:pom:2.12.4 from http://uk.maven.o ...
- EXCEPTION-TOMCAT
CreateTime--2016年10月24日16:22:12Author:Marydon声明:异常类文章主要是记录了我遇到的异常信息及解决方案,解决方案大部分都是百度解决的,(这里只是针对我遇到 ...
- 1、配置JAVA的环境变量
想要成功配置Java的环境变量,那肯定就要安装JDK,才能开始配置的. 想要成功配置Java的环境变量,那肯定就要安装JDK,才能开始配置的. 安装JDK 向导进行相关参数设置.如图: 正在安装程 ...
- 商家 APP 如何接入新版支付宝支付,老版本商家如何升级
代码地址如下:http://www.demodashi.com/demo/14006.html 前言 支付宝移动支付2.0版本对比1.0版本做了较大更新,新申请的商家都需要采用最新2.0版本 SDK ...
- hduoj------确定比赛名次
拓扑排序结合代码的完整理解 确定比赛名次 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Oth ...
- IT常用设备及服务器安全公告或漏洞地址pa安全预警微软安全公告 HP 安全公告AIX 安全公告REDHAT安全公告ORACLE 安全公告F5 安全公告 Cisco 安全公告Juniper 安全公告 VMware 安全公告IOS 安全公告
IT常用设备及服务器安全公告或漏洞地址: 微软安全公告 https://technet.microsoft.com/en-us/library/security/MS14-085 HP 安全公告 ht ...
- Wunderlist 云端任务管理(Todo list)工具
Wunderlist 是一个云端任务管理(Todo list)工具,支持 iPhone, iPad, Android, Windows, Mac OSX 以及 Web 端轻松同步,实现了真正意义上的跨 ...
- IP数据报格式和IP地址路由
一.IP数据报格式 IP数据报格式如下: 注:需要注意的是网络数据包以大端字节序传输,当然头部也得是大端字节序,也就是说: The most significant bit is numbered 0 ...