字符编码(续)---Unicode与ANSI字符串转换以及分辨字符编码形式
Unicode与ANSI字符串转换
我们使用windows函数MultiByteToWideChar将多字节字符串转换为宽字符字符串,如下:
int MultiByteToWideChar(
UINT uCodePage,
DWORD dwFlags,
PCSTR pMultiByteStr,
int cbMultiByte,
PWSTR pWideCharStr,
int cchWideChar);
uCodePage参数标识了与多字节字符串关联的一个代码页值。dwFlags参数允许我们进行额外的控制,它会影响带变音符号(比如重音)的字符。但是,一般情况下都不使用这些标
步,所以传给它的参数为0。pMultiByteStr参数指定要转换的字符串,cbMultiByte参数指定字符串的长度(字节数)。如果传给cbMultiByte参数的值是-1,函数便可自动判断源字符串的长度。函数将转换所得的Unicode版本的字符串写入内存缓冲区,其内存地址由pWideCharStr参数所指定。必须在cchWideChar参数中指定这个缓冲区的最大长度(字符数)。如果调用MultiByteToWideChar,并给cchWideChar参数传入0,函数就不会执行转换,而是返回一个宽字符数(包括终止字符'\0'),只有当缓冲区能够容纳该数量的宽字符时,转换才会成功。一般按照以下步骤将一个多字节字符串转换为Unicode形式。
(l)调用MultiByteToWideChar,为pMultiByteStr参数传入NULL,为cchWideChar参数传入0,为cbMultiByte参数传入-1。
(2)分配一块足以容纳转换后的Unicode字符串的内存。它的大小是上一个MultiByteToWideChar调用的返回值乘以sizeof(wchar_t)。
(3)再次调用MultiByteToWideChar,这一次将缓冲区地址作为pMultiByteStr参数的值传入,将第一次MultiByteToWideChar调用的返回值乘以sizeof(wchar_t)后得到的大小作为cchWideChar参数的值传入。
(4)使用转换后的字符串。
(5)释放Unicode字符串占用的内存块。
对应地,WideCharToMultiByte函数将宽字符字符串转换为多字节字符串,如下所示:
int WideCharToMultiByte(
UINT uCodePage,
DWORD dwFlags,
PCWSTR pWideCharStr,
int cchWideChar,
PSTR pMultiByteStr,
int cbMultiByte,
PCSTR pDefaultChar,
PBOOL pfUsedDefaultChar);
这个函数类似于MultiByteToWideChar函数。同样地,uCodePage标识了要与新转换的字符串关联的代码页。dwFlags参数允许我们指定额外的转换控制。这些标志会影响带变音符号的字符和系统不能转换的字符。但我们一般不需要进行这种程度的转换控制,因而为dwFlags参数传入0。
pWideCharStr参数指定要转换的字符串的内存地址,cchWideChar参数指出该字符串的长度(字符数)。如果为cchWideChar参数传入-1,则由函数来判断源字符串的一长度。
转换所得的多字节版本的字符串被写入pMultiByteStr参数所指定的缓冲区。必须在cbMultiByte参数中指定此缓冲区的最大大小(字节数)。调用WideCharToMultiByte函数时,如果将0作为cbMultiByte参数的值传入,会导致该函数返回目标缓冲区需要的大小。将宽字符字符串转换为多字节字符串时,采取的步骤和前面将多字节字符串转换为宽字符串的步骤相似;唯一不同的是,返回值直接就是确保转换成功所需的字节数,所以无需执行乘法运算。
注意,与MultiByteToWideChar函数相比,WideCharToMultiByte函数接受的参数要多两个,分别是pDefaultChar和pfUsedDefaultChar。只有一个字符在uCodePage指定的代码页中没有对应的表示时,WideCharToMultiByte函数才会使用这两个参数。在遇到一个不能转换的宽字符时,函数便使用pDefaultChar参数指向的字符。如果这个参数为NULL(这是很常见的一个情况),函数就会使用一个系统默认的字符。这个字符通常是一个问号。这对文件名来说非常危险,因为问号是一个通配符。
pfUsedDefaultChar参数指向一个布尔变量;在宽字符字符串中,如果至少有一个字符不能转换为对应的多字节形式,函数就会把这个变量设为TRUE。如果所有字符都能成功转换,就会把这个变量设为FALSE。我们可以在函数返回后测试该变量,验证宽字符字符串是否已成功转换。同样地,我们通常为此参数传入NULL值。
分辨字符编码形式
IsTextUnicode函数可以分辨字符是ANSI还是Unicode形式,该函数由AdvApi32.dll导出并在WinBase.h中声明:
BOOL IsTextUnicode(CONST PVOID pvBuffer, int cb, PINT pResult);
IsTextUnicode函数使用一系列的统计性和确定性方法来猜测缓冲区中的内容,存在一定误差性。
它的第一个参数是pvBuffer,标识了要测试的缓冲区的地址。此数据是一个void指针,因为还不知道即将面对的是一组ANSI字符还是Unicode字符。
第二个参数是cb,它指定pvBuffer指向的缓冲区的字节数。同样地,由于不知道缓冲区中是什么,所以cb是一个字节数而不是字符数。注意:我们不必指定整个缓冲区的长度。当然,函数测试的字节数越多,结果越精确。
第三个参数是pResult,这是一个整数的地址,在调用IsTextUnicode函数之前,我们必须初始化这个整数。在这个整数的初始值中,应指出希望IsTextUnicode执行哪些测试。也可以为其传入NULL,这种情况下,IsTextUnicode函数将执行它能执行的每一项测试。
如果IsTextUnicode函数认为缓冲区包含的是Unicode文本,就会返回TRUE;反之则返回FALSE。在pResult参数指向的整数中,如果指定了具体的测试项目,那么函数在返回之前,还全设置此整数中的相应位,以反映每个测试项目的结果。
字符编码(续)---Unicode与ANSI字符串转换以及分辨字符编码形式的更多相关文章
- 刨根究底字符编码之八——Unicode编码方案概述
Unicode编码方案概述 1. 前面讲过,随着计算机发展到世界各地,于是各个国家和地区各自为政,搞出了很多既兼容ASCII但又互相不兼容的各种编码方案.这样一来同一个二进制编码就有可能被解释成不 ...
- UNICODE和ANSI字符串的转换(解释了MultiByteToWideChar,WideCharToMultiByte,GetTextCharsetInfo,GetTextCharset,IsDBCSLeadByte,IsDBCSLeadByteEx,IsTextUnicode一共7个函数)
继上集故事<多字符集(ANSI)和UNICODE及字符串处理方式准则 >,我们现在有一些特殊需求: 有时候我们的字符串是多字符型,我们却需要使用宽字符型:有的时候却恰恰相反. Window ...
- 关于JAVA字符编码:Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换
我们最初学习计算机的时候,都学过ASCII编码. 但是为了表示各种各样的语言,在计算机技术的发展过程中,逐渐出现了很多不同标准的编码格式, 重要的有Unicode.UTF.ISO-8859-1和中国人 ...
- 字符编码:Unicode和UTF-8之间的关系
Unicode和UTF-8之间的关系 1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256 ...
- 字符编码:Unicode和UTF-8的关系
今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直看到晚上9点,才算初步搞清楚. 下面就是我的笔记,主要用来整理自己的思 ...
- 字符编码和python使用encode,decode转换utf-8, gbk, gb2312
ASCII码 标准ASCII码使用7位二进制数表示大写或小写字母,数字0到9标点符号以及在美式英语中使用的特殊控制字符. 在标准ASCII码中,最高位(b7)用作奇偶校验位,所谓奇偶校验,是指在代码传 ...
- 字符编码(ASCII、ANSI、GB2312、UTF-8等)系统梳理
引言 在显示器上看见的文字.图片等信息在电脑里面其实并不是我们看见的样子,即使你知道所有信息都存储在硬盘里,把它拆开也看不见里面有任何东西,只有些盘片.假设,你用显微镜把盘片放大,会看见盘片表面凹凸不 ...
- 字符编码(ASCII、ANSI、GB2312、UTF-8等)系统梳理(转载)
引言 在显示器上看见的文字.图片等信息在电脑里面其实并不是我们看见的样子,即使你知道所有信息都存储在硬盘里,把它拆开也看不见里面有任何东西,只有些盘片.假设,你用显微镜把盘片放大,会看见盘片表面凹凸不 ...
- python中字符编码及unicode和utf-8区别
ascii和unicode是字符集,utf-8是编码集 字符集:为每一个「字符」分配一个唯一的 ID(学名为码位 / 码点 / Code Point) 编码规则:将「码位」转换为字节序列的规则(编码/ ...
随机推荐
- 实战JAVA 高并发设计
一.同步(Synchronous)和异步(Asynchronous) 同步和异步通常用来形容一次方法调用,同步方法,调用者必须等到方法调用返回后,才能继续后续的行为,异步方法调用会立即返回,调用者就可 ...
- 暴力破解Windows RDP(3389)
RDP是远程桌面协议. $ nmap your_target Starting Nmap 7.01 ( https://nmap.org ) at 2016-09-20 17:29 CST Nmap ...
- 初识django框架
django框架 1.框架介绍 根据第一部分内容介绍,我们可以总结出一个web框架应该包含如下三部分:a.sockect服务.b.根据不同的url调用不同函数(包含逻辑).c.返回内容(模板渲染).常 ...
- c++ 基础知识 0001 const 知识2
1.const修饰函数返回值 (1)指针传递 如果返回const data,non-const pointer,返回值也必须赋给const data,non-const pointer.因为指针指向的 ...
- (三)java程序的编译和执行
编写java程序 eg class Demo { /* * 程序运行的入口 */ public static void main(String[] args) { System.out.println ...
- CSS 属性:touch-action
CSS 属性 touch-action 用于指定某个给定的区域是否允许用户操作,以及如何响应用户操作(比如浏览器自带的划动.缩放等). /* Keyword values */ touch-actio ...
- Oracle记录(四) 简单查询、限定查询、数据的排序
一.简单查询 SQL(Structured Query Language) 结构化查询语言,是一种数据库查询和程序设计语言,用于存取数据以及查询.更新和管理关系数据库系统.ANSI(美国国家标准学会) ...
- 微信 unionid 获取 解密数据
1.申请注册微信开放平台 open.weixin.qq.com 2.绑定公众号或者小程序到微信开放平台 3.微信公众号的话,使用微信网页授权获取 unionid https://mp.weixin. ...
- python基础篇之进阶
python基础篇之进阶 参考博客:http://www.cnblogs.com/wupeiqi/articles/5115190.html python种类 1. cpython 使用c解释器生产 ...
- 字节序(byte order)和位序(bit order)
字节序(byte order)和位序(bit order) 在网络编程中经常会提到网络字节序和主机序,也就是说当一个对象由多个字节组成的时候需要注意对象的多个字节在内存中的顺序. 以前我也基本只了 ...