windows代码页、区域-16.11.29

上传人:xiao****1972 文档编号:84092711 上传时间:2019-03-02 格式:DOC 页数:14 大小:180.35KB
返回 下载 相关 举报
windows代码页、区域-16.11.29_第1页
第1页 / 共14页
windows代码页、区域-16.11.29_第2页
第2页 / 共14页
windows代码页、区域-16.11.29_第3页
第3页 / 共14页
windows代码页、区域-16.11.29_第4页
第4页 / 共14页
windows代码页、区域-16.11.29_第5页
第5页 / 共14页
点击查看更多>>
资源描述

《windows代码页、区域-16.11.29》由会员分享,可在线阅读,更多相关《windows代码页、区域-16.11.29(14页珍藏版)》请在金锄头文库上搜索。

1、Windows代码页、区域Hanford2016年11月29日目 录目 录第1章 代码页11 代码页11.1 单字节字符集11.2 双字节字符集11.3 多字节字符集11.4 ANSI代码页22 枚举代码页33 查询代码页信息34 宽窄字符串45 字符串转换55.1 查表55.2 NlsDllCodePageTranslation6第2章 区域82.1 一个例子82.2 setlocale92.2.1 简单用法92.2.2 复杂用法92.3 #pragma setlocale102.4 rc 文件112.5 排序12I第1章 代码页第1章 代码页1 代码页代码页也叫字符集,它有两个特点:1、它

2、是一个字符集合;2、为了便于计算机处理。这个字符集合里,每个字符都有编码。可用一个字符串表示代码页,如:GB2312、GBK、GB18030、Big5也可以用一个整数表示代码页,如:20936表示GB2312、936表示GBK、54936表示GB18030、950表示Big51.1 单字节字符集代码页里,每个字符使用一个字节编码,这样的字符集就是单字节字符集SBCS(Single-byte Character Sets)1.2 双字节字符集代码页里,每个字符最多使用两个字节编码,这样的字符集就是双字节字符集DBCS(Double-byte Character Sets)1.3 多字节字符集代码

3、页里,某些字符的编码超过了一个字节,这样的字符集就是多字节字符集MBCS(Multi-byte Character Sets)。显然,双字节字符集属于多字节字符集,反过来多字节字符集不一定是双字节字符集。因为,有些代码页会用两个以上的字节表示一个字符。如:UTF-7、UTF-8。笔者发现一个规律:Windows中,编码超过两个字节的代码页,其数值超过50000,如下图所示:图1.1上图中,除了代码页“51949(EUC-朝鲜语)”,剩下超过50000的代码页,其编码用到的最大字节数均大于二。1.4 ANSI代码页ANSI代码页具有如下特点:1、编码0至127符合ANSI(American Na

4、tional Standards Institute美国国家标准学会)制定的ASCII编码标准;2、它是由微软制定并实现的。如:GB2312也符合第1条,但它不是ANSI代码页,因为这套编码属于中国的国标,不是微软制定的。由微软实现的GBK才是ANSI代码页;3、它是双字节字符集,亦即编码最多两个字节。下图中,有ANSI标志的就是ANSI代码页。简体中文Windows,使用的代码页是936,即GBK。图1.22 枚举代码页可使用API函数EnumSystemCodePages,枚举系统的代码页。下面的代码枚举代码页,存入变量s_mapCodePage中:static std:map s_map

5、CodePage;static BOOL CALLBACK EnumCodePagesProc(LPTSTR lpString) s_mapCodePage_tcstoul(lpString,NULL,10); return TRUE;/枚举代码页,存入s_mapCodePage s_mapCodePage.clear(); EnumSystemCodePages(EnumCodePagesProc,CP_INSTALLED);3 查询代码页信息可使用GetCPInfoEx函数获得代码页的信息。代码如下:/遍历s_mapCodePage,获取每个代码页的说明 CPINFOEX ci; for(

6、std:map:iterator it = s_mapCodePage.begin() ;it != s_mapCodePage.end();+it) if(GetCPInfoEx(it-first,0,&ci) it-second = ci.CodePageName; 结构CPINFOEX里,多字节编码的信息不全只有首字节的范围信息,没有其它字节的范围信息。可以通过编码找出其余字节的范围信息。思路就是:调用WideCharToMultiByte函数,将00xFFFF的UTF-16编码转换为指定代码页的编码,并确定各个字节的范围。如下图所示,计算出了GBK的编码范围:图1.3注意:1、上图中,

7、一字节的编码范围为0x00,0xFF,最多只能有256个。何以有41198个之多?原因在于WideCharToMultiByte将UTF-16字符映射为GBK字符时,会有多个字符映射为同一个字符的情况;2、上图的编码范围只显示最小值和最大值,还不足够精细;3、实现上述功能的VC+代码已被笔者上传至git服务器,网址如下:https:/ 宽窄字符串Windows 下,使用VC+编程。会遇到三类字符串:1、宽字符串,即UTF-16编码的字符串。每个字符固定占用两个字节。处理宽字符串的API函数一般以W结尾,如:CreateWindowW、MessageBoxW2、窄字符串,即字符串中的字符均属于某

8、个ANSI代码页。每个字符占用一至两个字节。处理窄字符串的API函数一般以A结尾,如:CreateWindowA、MessageBoxA3、多字节字符串,即字符串中字符编码的字节数超过了两个。如:UTF-8、GB18030这类字符串必须转换为宽字符串或窄字符串后,才能被Windows API使用。Windows系统中,宽字符串不会产生歧义它总是UTF-16编码;多字节字符串(包括窄字符串)在不同的代码页下会有不同的解释,所以必须明确窄字符串所属的代码页,否则就会产生乱码。5 字符串转换宽窄字符串的转换由WideCharToMultiByte(宽字符串转换为多字节字符串)和MultiByteTo

9、WideChar(多字节字符串转换为宽字符串)完成。5.1 查表WideCharToMultiByte和MultiByteToWideChar的实质工作主要就是查表。如下面的代码转换宽字符串“编码”为窄字符串:char szStr64;WideCharToMultiByte(CP_ACP,0,L编码,-1,szStr,64,NULL,NULL);这一行代码做了什么?查看注册表HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlNlsCodePage图1.4根据上图可知:CP_ACP表示代码页936。再根据936可以查到文件c_936.nls。nls文

10、件其实就是UTF-16编码与ANSI编码的对照表。具体请参考博文:http:/demon.tw/copy-paste/nls-file-format.htmlWideCharToMultiByte根据c_936.nls文件中的对照表,把“编码”由UTF-16编码转换为代码页为936的编码。5.2 NlsDllCodePageTranslation有些编码不适合查表,如:UTF-7编码与UTF-16编码的转换并不是简单的字符对应关系,无法查表完成。编码超过两个字节的,无法查表。如:GB18030、UTF-8的编码均超过了两个字节,无法使用nls文件存储编码对照表。这类情况下,WideCharTo

11、MultiByte和MultiByteToWideChar是如何实现的呢? 查看注册表,代码页54936(GB18030)对应的文件是c_g18030.dll。图1.5在C:WindowsSystem32和C:WindowsSysWOW64目录下,均能找到c_g18030.dll这个文件。System32目录下是64位的,SysWOW64目录下是32位的。这个dll文件,导出了函数NlsDllCodePageTranslation。图1.6也就是说,对于无法查表完成的编码转换。WideCharToMultiByte和MultiByteToWideChar会LoadLibrary该代码页对应的d

12、ll文件,然后调用该dll文件里的导出函数NlsDllCodePageTranslation,完成编码的转换工作。7第2章 区域第2章 区域2.1 一个例子首先看一个例子#include void main() puts ( 窄字符串); _putws(L宽字符串);运行结果如下:图2.1为什么宽字符串没有被显示出来?因为调用C函数之前,没有设置C函数的代码页为GBK。为此,修改代码如下:#include #include void main() setlocale(LC_ALL,.936); /设置代码页为 GBK puts ( 窄字符串); _putws(L宽字符串);运行结果如下:图2.

13、22.2 setlocaleMSDN里关于setlocale函数的说明,第二个参数有些复杂,如下所示:locale : lang_country.code_page | .code_page | | NULL2.2.1 简单用法用 法示 例说明.code_pagesetlocale(LC_ALL,.936);设置代码页为936setlocale(LC_ALL,);设置代码页为系统默认值对于简体中文而言就是936NULLsetlocale(LC_ALL,NULL);获取设置,如:setlocale(LC_ALL,);之前调用setlocale(LC_ALL,NULL);将返回Csetlocale(LC_ALL,);之后调用setlocale(LC_ALL,NULL);将返回Chinese (Simplified)_Peoples Republic of China.9362.2.2 复杂用法setlocale(LC_ALL,);之后调用setlocale(LC_ALL,NULL);将返回Chinese (Simplified)_Peoples Republic of China.936。这个返回值就是lang_country.code_page下划线之前的是语言,下划线与小数点之间的是国家或地区,小数点之后的是代码页。语言、国家或地区这两个参数该怎么填?可使用Enum

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 大杂烩/其它

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号