编码(ACSII unicod UTF-8)、QT输出汉语乱码长远剖析

总结:

http://bbs.ylmf.net/forum.php?mod=viewthread&tid=1953972&extra=%26page%3D1

1.
qt输出中文乱码原因剖析

折腾,折腾!VM7.0 虚拟机安装雪豹Mac OS 斯诺 Leopard 10.6!

我是从其他地点转发过来的(图片 1太懒了真正不想自己写,图片我都截好了,又删了)
他给的VMware
workstation,darwin.ISO我不敢用,就把此前自己的帖子里的复制过来了,VMware
workstation是从下载吧里找的,我直接都用的那几个VM(我怕她的网盘地址失效了)

虚拟机安装Mac率领ISO(这么些帖子里有
empireEFIv1085.iso,Rebel_EFI.iso,darwin.iso)

VMware
workstation:vmware虚拟机|VMware
Workstation(vmware虚拟机下载)V7.1.1 Build 282343不难尤其版 –
下载吧

苹果Mac OS
X下载[苹果雪豹操作系统正式版].snowleopard_10a432_userdvd.dmg (6.13
GB)

(电驴上的,因为VeryCD封了,我就放ed2k链接)
1、以管理员身份运行VM,开端新建虚拟机

图片 2

2、选拔标准设置

图片 3

3、接纳你下载的RebelEFI指引盘ISO:
图片 4

4、选取虚拟机种类,大家挑选Other,版本选取FreeBSD
64-bit
图片 5

5、采用你虚拟机的存放地方
图片 6

6、设置虚拟机硬盘大小,指出设置值为15G上述
图片 7

7、定制虚拟机的硬件配备,为了方便安装提出把虚拟机内存设为1G之上,并把光盘驱动器改为SCSI,最后再所软驱删掉
图片 8

8、虚拟机安装到位后,不要登时启动虚拟机,大家还要调整下虚拟机的配置文件。
这一步相当重大,不然雪豹安装完后有时候会活动重启,虚拟CPU会自行关闭(我也是在网上来看的,具体是或不是如此没有测过)
  打开新建虚拟机的随处目录,用记事本或写字板打开以.vmx为增添名的文本,到guestOS =
那行,把它背后双引号“”里的情节改为darwin10,改后即为:
guestOS =
“darwin10″保存退出,OK了,虚拟机设置成功完结。
打开虚拟机后,点击“Options”,双击General,再看Version:那里,是还是不是多出了Mac
OS X Server
10.6这一项?原来是不曾的啊。好啊,现在就足以健康安装雪豹了!
正如图所示:

图片 9

其三有些:安装雪豹系统

      安装雪豹到虚拟机里,最要害的就是指引,
A、那里自己先用Rebel EFI.iso率领盘来设置,
B、安装及设定好系统后,再用darwin.iso来指引使用系统,而且它会自行进入的。
表达:当然使用Rebel EFI.iso也可以开展指引,但在动用进程中,显然感觉到比darwin.iso指引的连串要慢。(我日常是使用darwin.iso来指点的,萝卜白菜各有所爱嘛)
1、接通虚拟机的电源,启动虚拟机,进入下图的界面,须要我们插入豹雪安装盘,大家先把虚拟机光驱中的Rebel
EFI.iso弹出,装上豹雪安装盘。即可进入安装界面了。哈哈,有点快乐了!波儿个。。。。
图片 10

图片 11

图片 12

2、选拔简体普通话作为主语言
图片 13

3、点击继续进入此步最,最好把虚拟机放大
到全屏,不然看不到顶上的工具栏,此时系统绝非找到硬盘。我们须要通过工具栏上的磁盘工具给虚拟机的硬盘分区。分区格局大家挑选,GUID分区表,最后点
击应用。关掉磁盘工具,再次来到安装界面,此时大家会看到新的磁盘已经被系统发现,如图:

图片 14

图片 15

图片 16

图片 17

图片 18

4、安装到位后,可能会唤起您从未被安装成功,一点关系并未,大家再度起动电脑,将豹雪的ISO安装盘取出,放入darwin.iso光盘举办指导启动。至此水到渠成。

图片 19

5、安装虚拟机的声卡、显卡驱动,先安装虚拟机的VMSTOOLS(启动后,darwin.iso光盘里有),
将方面下载的驱动程序解压到主机,并将文件夹共享给MAC,
透过MAC桌面上的共享文件夹即可安装虚拟驱动程序了
图片 20

 

qt的编程环境默认是utf-8编码格式(至于编码见下文知识要点一);

cout << "中文" << endl;

程序运行,程序并不认识ANSI,UTF-8以及其它其余编码.系统只略知一二处理你给它的字符的**二进制表示.**

 

有关  “中””文”
的3种编码二进制内容:

 

ANSI(GBK): 0xd6d0  0xcec4

 

UTF-8: 0xe4b8ad 0xe69687

 

Unicode: 0x4e2d 0x6587

1)在简体普通话Windows下的控制台突显环境是ANSI编码(代码页936,
GBK),先明了那点.

重大不一致,MinGW看到的是”0xe4b8ad”和”0xe69687″(gcc默许UTF-8).注意,用MinGW编译的源文件中有中文宽字符必须保留为UTF-8编码.

2)测试代码:

#include <iostream>
using namespace std;

int main()
{
    char a[] = "中文";
    cout << a << endl;
    return 0;
}

3)经在qt5.8中测试乱码;

分析:参见(下文知识要点一,知识要点二)不难发现UTF-8只是一种编码进行方案,并不是事实上编码;再参见(文化要点五),程序运行是能过最终编译完成的二进制码输出

在vs2017中,用unicode编码格局,编译运行输出正常;原因我想很好精通了,当程序编译后保存的是“普通话”unicode二进制编码,而决定台出口时CodePage
(GBK 936)
这么些CodePage就会根据映射表去挨家挨户对应GBK中的汉语字,再进行输出;

而在qt5.8(MinGW)中,输出则是乱码;因为qt5.8默认的编码情势是UTF-8;当程序编译后保存的是“汉语”UTF-8二进制编码,而控制台出口时CodePage
(GBK 936)
那么些CodePage就会基于映射表去各样对应GBK中的中文字,好像何地不对,好了,难点就出在此刻了,CodePage是各国与unicode的映射表,并不是与UTF-8的(文化要点二CodePage),在qt5.8(MinGW)中,原程被编译二进制文件,保存下去的“粤语”地址是,UTF-8编码,而映射表是在unicode中找内容,再开展输出,自然就是乱码;

网上解决方法1.修改注册表CodePage 65001  经测试仍然乱码

辩护剖析:CodePage(GBK
936)找不到映射,那么把控制台换成UTF-8;那么然先保存的,UTF-8国语,再经过UTF-8对应的汉字码,不就能出口汉字;理论好像可行,但在自己的win7
64位中文系统上,qt5.8,vs2017均战败;

可能原因:我系统中cmd控制台并不支持UTF-8编码形式(有时机在win10中测试后再做补偿)

解决方法2:通过(知识点一,二,
五),统计,当要在控制台举行汉语输出时,编码格局应该保留为unicode,或ACSI(GBK);

4)关于宽字节出口乱码的题材;

出口宽字节华语(详见文化要点四):例

#include <iostream>
using namespace std;

int main()
{
    wcout << L"中文" << endl;
    return 0;
}

出口则要用wcout而不能是cout;关于宽字符详见;知识要点二后续,**知识要点三**

在vs2017中,输出汉语,为空;

1、cout和wcout

 在C++下,cout可以一贯出口汉语,但对于wcout却极度。对于wcout,须要将其locale设为本土语言才能出口粤语:

 wcout.imbue(locale(locale(),””,LC_CTYPE));

 也有人用如下语句的,但那会变动wcout的持有locale设置,比如数字“1234”会输出为“1,234”。

 wcout.imbue(locale(“”));

 在C语言下,locale设置为本土语言(C语言中唯有全局locale)就足以健康输出了:

 setlocale(LC_CTYPE, “”);

 在qt5.8(MinGW)环境中,以上并不实用,近年来还没找到出口汉语的办法,未完待续;

 

文化要点一:编码**

ASCII:
早期的字符集,7位,128个字符,包含大小写a-z字母,0-9数字以及一些说了算字符.

  扩展ASCII: 1个字节8位,只用7位不合理.于是第8位用于增添ASCII字符集,那样就又多了128个字符.于是用着后128个字符来增添表示如拉丁字母,希腊(Ελλάδα)字母等特殊符号.但难题是澳大利亚那一票国家很多并行都有着不等同的独特字母,一起塞进后128个家喻户晓不够,于是代码页出现了.

**  Code Page(代码页)**:
1个字节前128个字符我们集合和ASCII一样,而后128个字符,按照分歧系统所谓代码页来不一致各样语言不一致等的假名和符号.

**  DBCS(双字节字符集)**:
对于亚洲江山,后128个字符如故惊慌失措包蕴多量的象形文字,DBCS正是为此的一个化解方案.DBCS由一个或八个字节表示一个字符,那表达DBCS并不一定是三个字节,对于如英文字母,是向ASCII包容的,仍然由1个字节表示,而对此如普通话则用2个字节表示.英文和中文可以统一地处理,而区分是或不是为普通话编码的格局是2个字节中的高字节的第一位为1,就不可能不检查前边紧跟着的不胜字节,2个字节一起解释为1个字符.GB2312,GBK到GB18030都属于DBCS.别的,简体中文Windows下的ANSI编码寻常是指GBK(代码页936).

DBCS很大难题在于字符串的字符数不能经过字节数来决定,如”粤语abc”,字符数是5,而字节数是7.对此用++或–运算符来遍历字符串的程序员来说,这几乎就是恐怖的梦!

  Unicode: 学名为”Universal Multiple-Octet
Coded Character Set
“,简称”UCS“.UCS可以视作是”Unicode Character
Set”的缩写.

也是一种字符集/字符编码方法,它统一用唯一的字符集来含有那么些星球上多数言语的书写系统.UCS向ASCII包容(即前128个字符是如出一辙的),但并不包容DBCS,因为任何字符在UCS中被重复编码(重新安插地点).

UCS有二种格式:UCS-2和UCS-4.前者用2个字节(16位)编码,后者用4个字节(实际上只用31位)编码.USC-4前2个字节都为0的有些号称BMP(基本多语言平面),就是说BMP去掉前2个零字节就是UCS-2.近年来的UCS-4规范中还从未任何字符被分配在BMP之外.(说白了,USC-4就是为当16位的USC-2都被分配完时候做再做增添用的,现在还没用到)

  UTF-8,UTF-16,UTF-32: “Unicode transformation
format”(UTF)
 ,即Unicode的传输格式.Unicode规定了怎么编码字符,而UTF规定怎么将一个Unicode字符单元映射到字节序来传输或保存.

UTF-16UTF-32各自代表以16位和32位为一个Unicode单元进行编码,其实UTF-16对应就是UCS-2,UTF-32对应就是UCS-4(UCS-2和UCS-4是破旧的传教,应摒弃).
其它,平日说的Unicode就是指UTF-16.

UTF-8是关键!要是统一Unicode都用2字节表示,英文字母觉得温馨就很吃亏(高字节始终是0字节).UTF-8提供了一种灵活的解决办法:以单字节(8bit)作为编码单元,变长多字节编码格局.如ASCII字母继续接纳1字节储存,普通话汉字用3字节囤积,其他最多可直6字节.

UTF-16和UTF-32要求有字节序标志BOM(FEFF)解决大端小端难点.UTF-8没有字节序的标题(因为以1个字节为单元).

 

===============================================================================

任何注意点:

DBCS准确说,应该是MBCS(Multi-Byte Chactacter
System, 多字节字符系统).

字符集(Charset)和编码(Encoding)注意分裂.如GBK,GB2312以及Unicode都既是字符集,也是编码格局,而UTF-8只是编码格局,并不是字符集.

Linux下The GUN
C Library(从glibc
2.2起来)中宽字符wchar_t是以32位的Unicode(USC-4)表示.如宽字符”中”字为
“0x00004e2d”.而Windows下的CRT使用宽字符仍是16位的.

 

知识要点二:关于Unicode的体味(加深对编码的精晓)

析Unicode和UTF-8 

一、首先说多美滋下现行常用的有的编码方案:
1.
在神州,大陆最常用的就是GBK18030编码,除此之外还有GBK,GB2312,那多少个编码的涉嫌是那般的。
最早制定的汉字编码是GB2312,包蕴6763个汉字和682个其余符号
95年再度修订了编码,命名GBK1.0,共收录了21886个记号。
随后又推出了GBK18030编码,共收录了27484个汉字,同时还引用了藏文、蒙文、维吾尔文等主要的少数民族文字,现在WINDOWS平台必要求襄助GBK18030编码。
按照GBK18030、GBK、GB2312的依次,3种编码是向下包容,同一个中国字在四个编码方案中是一致的编码。
2.  广东,香江等地运用的是BIG5编码
3.  日本:SJIS编码
二、Unicode
  即使把种种文字编码形容为各处的白话,那么Unicode就是世界各国合营开发的一种语言。
  在那种语言环境下,不会再有语言的编码争执,在同屏下,可以显得任何语言的内容,那就是Unicode的最大利益。
  那么Unicode是怎么着编码的呢?其实分外简单。
  就是将世界上保有的文字用2个字节统一进行编码。可能你会问,2个字节最多可以代表65536个编码,够用吗?
  南韩和东瀛的绝半数以上中国字都是从中国传出过去的,字型是一心平等的。
  比如:“文”字,GBK和SJIS中都是同一个汉字,只是编码差别而已。
  那样,像那样统一编码,2个字节就曾经够用容纳世界上富有的言语的绝超过半数文字了。
UCS-2 与UCS-4
  Unicode的学名是”Universal Multiple-Octet Coded Character
Set”,简称为UCS。
  现在用的是UCS-2,即2个字节编码,而UCS-4是为了防备未来2个字节不够用才开发的。UCS-2也号称基本多文仲平面。
  UCS-2转换来UCS-4只是简容易单的在面前加2个字节0。
  UCS-4则第一用于保存帮助平面,例如Unicode 4.0中的第二拉扯平面
  20000-20FFF – 21000-21FFF – 22000-22FFF – 23000-23FFF – 24000-24FFF

  • 25000-25FFF –   26000-26FFF   - 27000-27FFF – 28000-28FFF –
    29000-29FFF – 2A000-2AFFF – 2F000-2FFFF
      总共扩展了16个接济平面,由原本的65536个编码伸张至接近100万编码。
    三、 兼容codepage
      那么既然统一了编码,怎样协作原先各国的文字编码呢?
      那么些时候就要求codepage了。
      什么是codepage?codepage就是各国的文字编码和Unicode之间的映射表。
      比如简体汉语和Unicode的映射表就是CP936,点那里查看官方的映射表。
      以下是多少个常用的codepage,相应的改动上边的地点的数字即可。
      codepage=936 简体汉语GBK
      codepage=950 繁体中文BIG5
      codepage=437 美利坚同盟国/加拿大意大利共和国语
      codepage=932 日文
      codepage=949 韩文
      codepage=866 俄文
      codepage=65001 unicode UFT-8
    最终一个65001,据个人知道,应该只是一个虚拟的映射表,实际只是一个算法而已。
    从936中随意取一行,例如:
    0x9993 0x6ABD #CJK UNIFIED IDEOGRAPH
    眼前的编码是GBK的编码,后面的是Unicode。
    经过查那张表,就能简单的贯彻GBK和Unicode之间的转换。
    四、UTF-8
      现在驾驭了Unicode,那么UTF-8又是怎么啊?又为啥会现出UTF-8呢?
      ASCII转换成UCS-2,只是在编码前插入一个0x0。用那一个编码,会席卷部分控制符,比如
    ” 或
    ‘/’,那在UNIX和一部分C函数中,将会生出严重错误。由此可以一定,UCS-2不合乎当作Unicode的外部编码。
      因而,才落地了UTF-8。那么UTF-8是怎样编码的?又是哪些化解UCS-2的标题吧?
    例:
    E4 BD A0        11100100 10111101
    10100000
    这是“你”字的UTF-8编码
    4F 60          01001111
    01100000
    这是“你”的Unicode编码
    有关汉字根据UTF-8的编码规则,分解如下:xxxx0100 xx111101 xx100000
    把除了x之外的数字拼接在同步,就改成“你”的Unicode编码了。
    瞩目UTF-8的最前面3个1,表示所有UTF-8串是由3个字节构成的。
    经过UTF-8编码之后,再也不会出现敏感字符了,因为最高位始终为1。
    以下是Unicode和UTF-8之间的变换关系表:
    U-00000000 – U-0000007F: 0xxxxxxx
    U-00000080 – U-000007FF: 110xxxxx 10xxxxxx
    U-00000800 – U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
    U-00010000 – U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
    U-00200000 – U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
    U-04000000 – U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
    10xxxxxx、
    Unicode编码转换来UTF-8,针对汉语,简单的把Unicode字节流套到x中就改成UTF-8了。

续篇:

unicode在windows api中的应用
    实际上,常提到的Win32
API的称号并不是它们的实事求是名称。那一个名称仅仅是一对宏,你可以在PSDK的头文件中找到那几个宏对用的函数名称。所以,若是PSDK的文档提到一个函数,如CreateFile,开发人士应该发现到它仅仅是一个宏。它的实际名称是CreateFileA和CreateFileW。是的,它表示了“五个”函数名,而不是一个,是同一个函数在分歧Win32函数的多个区其余版本。以’A’结尾的函数接受ANSI字符串(char *),即Unicode字符串(wchar_t
*)而在vs中得以用WCHAR宏代替,即wchar_ts型字符串。三种版本的函数都在模块kernel32.dll中贯彻,假使你的编程环境是Unicode则,则宏CreateFile在编译是会被CreateFileW代替,否则用CreateFileA代替。

PSDK的字符串解决方案:TCHARs
   
为了幸免为不相同的windows操作系统开发分化版本的PSDK,微软制定了一个联合的字符串类型TCHARs。TCHAR以及其它的照应的宏在头文件WinNT.h中有定义。程序员在先后中不须求为利用char仍旧wchar_t而纠结,只须要运用宏TCHAR就足以了。按照Unicode环境是还是不是存在,编译器会活动举办对应的转移。同样道理,程序员不需求为使用’A’如故’W’型Win32
API函数纠结。

对于较先前时期的系统均使用ACSI编码,而在最新系统中则都统一为unicode编码(如:手机系统)

 

知识要点三:
L”……”,
_T(), _TEXT
,TEXT()

L”……”: L是意味字符串资源转为宽字符的保存(经常转为unicode),却未必是unicode字符,那与编译器完结相关。

_T(” ……”) 是一个适配的宏     #ifdef _UNICODE(当系统环境是unicod下)
_T就是L   而当系统环境是ACSI 
_T就是ANSI的。(有方便早期windows系编程文件的移植,达到新旧种类相互)

_T、_TEXT、TEXT 三者效果等同

tchar.h是运作时的头文件,_T、_TEXT 根据_UNICODE来确定宏
winnt.h是Win的头文件根据,TEXT 依据UNICODE 来确定宏

万一须要同时选取这3个宏,则需同时定义 UNICODE 和 _UNICODE
VS2010之后的版本中
,设置:项目–属性–配置属性–常规–字符集–使用Unicode字符集,
那么编译器命令选项中真的同时插足了_UNICODE和UNICODE。

文化要点四: c++ 的cout 与
wcout**

cout << "hello world!" << endl; //ACSI 编码输出

cout << L“hello world!” <<endl;// unicode 输出

当输出双字节编码到控制台时,cout输出的将是地点而不要内容那时就要用到wcout;

改为:

cout << "hello world!" << endl; //ACSI 编码输出

wcout << L“hello world!” <<endl;// unicode 输出

** 


文化要点五:编译连接进程

1.预处理 生成.i文件

C++的预处理是指在C++程序源代码被编译往日,由预处理器对C++程序源代码举行的拍卖。这些进度并不对先后的源代码举行辨析。

此处的预处理器(preprocessor)是指真的的编译开头以前由编译器调用的一个独立程序。

预处理器主要负责以下的几处

1.宏的替换

2.刨除注释

3.拍卖预处理指令,如#include,#ifdef

 2.编译和优化 生成汇编.s原文件

词法分析 — 识别单词,确认词类;比如int
i;知道int是一个系列,i是一个最首要字以及判断i的名字是不是合法
语法分析 — 识别短语和句型的语法属性;

语义分析 — 确认单词、短语和句型的语义特征;

代码优化 — 修辞、文本编辑;

代码生成 — 生成译文。

3.生成**.o**目的文件


汇编进度实际上指把汇编语言代码翻译成目标机器指令的进度。

在终极的对象文件中

除了具有自己的数目和二进制代码之外,还要至少提供2个表:未缓解符号表和导出符号表,分别报告链接器自己索要哪些和可以提供哪些。

编译器把一个cpp编译为对象文件的时候,除了要在对象文件里写入cpp里富含的数码和代码,还要至少提供3个表:未缓解符号表,导出符号表和地址重定向表。
未缓解符号表提供了所有在该编译单元里引用不过定义并不在本编译单元里的符号及其出现的地方。
导出符号表提供了本编译单元具有定义,并且愿意提须求其它编译单元使用的记号及其地址。
地址重定向表提供了本编译单元所有对自身地址的引用的记录。

4.链接

由汇编程序生成的目的文件并不可以登时就被实践,其中可能还有众多没有缓解的题材。例如,某个源文件中的函数可能引用了另一个源文件中定义的某部符号(如变量或者函数调用等);在程序中或许调用了某个库文件中的函数,等等。所有的这么些标题,都亟需经链接程序的拍卖方能得以缓解。