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. Dojo仪表盘

    Dojo提供了非常好的仪表盘显示,效果如下: <!DOCTYPE html> <html> <head> <title>Dojo仪表盘</titl ...

  2. ng $scope与$rootScope的关系

    $scope与$rootScope的关系:①不同的控制器之间 是无法直接共享数据②$scope是$rootScope的子作用域对象$scope的id是随着控制器的加载顺序依次递增,$rootScope ...

  3. will-change 提高页面滚动、动画等渲染性能

    一.先来看一个例子 视差滚动现在不是挺流行的嘛,然后Chris Ruppel当其使用background-attachment: fixed实现背景图片不随滚动条滚动而滚动效果的时候,发现,页面的绘制 ...

  4. RIPng 知识要点

    RIPng  --------------------------------------------------------- UDP:521 多播地址:FF02::9 -------------- ...

  5. .NET面试题总结

    1.c#垃圾回收机制 从以下方面入手展开:  1.压缩合并算法   2.代的机制  3.GC调用终结器 2.委托和事件 先说它的定义:委托的本质是类,类型安全的指针,然后从用途上考虑,事件是包装的委托 ...

  6. JDBC 2 封装

    1 封装 新建类 DBConnUtil  ,新建database.properties 文件储存链接信息如下所示 jdbcDriver=com.mysql.jdbc.Driver jdbcUrl=jd ...

  7. GIT多人合作开发

    . 建立代码仓库(专门用于团队开发的代码仓库) ============================================================================ ...

  8. npm 私服工具verdaccio 安装配置试用

      1. 安装 npm install -g verdaccio 2. 启动 verdaccio // 界面显示信息 Verdaccio doesn't need superuser privileg ...

  9. 【CSS3】 - 初识CSS3

    .navdemo{ width:560px; height: 50px; font:bold 0/50px Arial; text-align:center; margin:40px auto 0; ...

  10. datetimebox

    $.extend($.fn.datagrid.defaults.editors, { datetimebox: {// datetimebox就是你要自定义editor的名称 init: functi ...