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字符串转换以及分辨字符编码形式的更多相关文章

  1. 刨根究底字符编码之八——Unicode编码方案概述

    Unicode编码方案概述   1. 前面讲过,随着计算机发展到世界各地,于是各个国家和地区各自为政,搞出了很多既兼容ASCII但又互相不兼容的各种编码方案.这样一来同一个二进制编码就有可能被解释成不 ...

  2. UNICODE和ANSI字符串的转换(解释了MultiByteToWideChar,WideCharToMultiByte,GetTextCharsetInfo,GetTextCharset,IsDBCSLeadByte,IsDBCSLeadByteEx,IsTextUnicode一共7个函数)

    继上集故事<多字符集(ANSI)和UNICODE及字符串处理方式准则 >,我们现在有一些特殊需求: 有时候我们的字符串是多字符型,我们却需要使用宽字符型:有的时候却恰恰相反. Window ...

  3. 关于JAVA字符编码:Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换

    我们最初学习计算机的时候,都学过ASCII编码. 但是为了表示各种各样的语言,在计算机技术的发展过程中,逐渐出现了很多不同标准的编码格式, 重要的有Unicode.UTF.ISO-8859-1和中国人 ...

  4. 字符编码:Unicode和UTF-8之间的关系

    Unicode和UTF-8之间的关系 1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256 ...

  5. 字符编码:Unicode和UTF-8的关系

    今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直看到晚上9点,才算初步搞清楚. 下面就是我的笔记,主要用来整理自己的思 ...

  6. 字符编码和python使用encode,decode转换utf-8, gbk, gb2312

    ASCII码 标准ASCII码使用7位二进制数表示大写或小写字母,数字0到9标点符号以及在美式英语中使用的特殊控制字符. 在标准ASCII码中,最高位(b7)用作奇偶校验位,所谓奇偶校验,是指在代码传 ...

  7. 字符编码(ASCII、ANSI、GB2312、UTF-8等)系统梳理

    引言 在显示器上看见的文字.图片等信息在电脑里面其实并不是我们看见的样子,即使你知道所有信息都存储在硬盘里,把它拆开也看不见里面有任何东西,只有些盘片.假设,你用显微镜把盘片放大,会看见盘片表面凹凸不 ...

  8. 字符编码(ASCII、ANSI、GB2312、UTF-8等)系统梳理(转载)

    引言 在显示器上看见的文字.图片等信息在电脑里面其实并不是我们看见的样子,即使你知道所有信息都存储在硬盘里,把它拆开也看不见里面有任何东西,只有些盘片.假设,你用显微镜把盘片放大,会看见盘片表面凹凸不 ...

  9. python中字符编码及unicode和utf-8区别

    ascii和unicode是字符集,utf-8是编码集 字符集:为每一个「字符」分配一个唯一的 ID(学名为码位 / 码点 / Code Point) 编码规则:将「码位」转换为字节序列的规则(编码/ ...

随机推荐

  1. 旧书重温:0day2【4】动态获取函数地址

    通过以上3篇文章的学习,我们已经可以获取到kernel32.dll的地址了下一步 我们就是获取几个重要的函数 1.GetProcAddress 2.LoadLibrary 有了这两个函数很多函数都可以 ...

  2. touch-action属性

    CSS属性 touch-action 用于指定某个给定的区域是否允许用户操作,以及如何响应用户操作(比如浏览器自带的划动.缩放等). /* Keyword values */touch-action: ...

  3. 使用iptables nat进行端口转发

    1.将发向HostA:PortA的请求转发到HostB:PortB iptables -t nat -A PREROUTING -p tcp -i eth0 -d HostA --dport Port ...

  4. cocos2d-x3.16 default模式项目 Android Studio C++文件编译失败问题

    gradle sync正常,但是在编译的时候几乎自己写的Classes里全部c++文件的最后一行都在报错,原来是3.16 模板cpp-template-default内的Android.mk文件内这一 ...

  5. EL表达式可以直接放在url的“ ”里面

    <div class="hc-prm-search search flr"> <form action="/userCenter/projectInfo ...

  6. 剑指offer-第三章高质量代码(树的子结构)

    题目:输入两个二叉树A和B,判断B是不是A的子结构. 思路:遍历A树找到B树的根节点,然后再判断左右子树是否相同.不相同再往下找.重复改过程. 子结构的描述如下图所示: C++代码: #include ...

  7. webpack新版本4.12应用九(配置文件之多种配置类型)

    除了导出单个配置对象,还有一些方式满足其他需求. 导出为一个函数 最终,你会发现需要在开发和生产构建之间,消除 webpack.config.js 的差异.(至少)有两种选项: 作为导出一个配置对象的 ...

  8. Yii登录验证和全局访问用户ID

    注意:Yii默认的代码,Yii::app()->user->id返回的不是我们想要的用户ID,而是用户名.因此在useridentity类中要用一个变量来存储登录用户的ID,然后重载get ...

  9. Anaconda 使用conda常用命令

    1.首先在所在系统中安装Anaconda.可以打开命令行输入conda -V检验是否安装以及当前conda的版本. 2.conda常用的命令. 1)conda list 查看安装了哪些包. 2)con ...

  10. 在web.config中配置httpHandlers节点是的说明

    <system.web> <httpHandlers> <add verb="*" path="*.lcj" type=" ...