字符编码(续)---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) 编码规则:将「码位」转换为字节序列的规则(编码/ ...
随机推荐
- mysql基本操作(重点)
显示数据库 show databases 进入指定数据库 use 数据库名称 创建数据库 create database 数据库名称 default character set=utf8 删除数据库 ...
- RPi 2B QEMU 模拟树莓派
/******************************************************************************** * RPi 2B QEMU 模拟树莓 ...
- LUAROCKS 报错解决办法
用luarocks 加载包时报错 Warning: falling back to curl - install luasec to get native HTTPS support 此时先安装 ./ ...
- rebar安装及创建项目
rebar作为erlang开发中编译,构建,发布,打包,动态升级的常用工具,下面我记录下rebar工具的安装及使用 从源码安装rebar 1. 建立文件 install_rebar.sh 2. 拷贝如 ...
- JDBC 4 PreparedStatement 与Statement 的区别
1 有安全性 PreparedStatement 可以由于不是使用拼接,防止了sql注入,提高了安全性. 2 更方便 PreparedStatement 可以自动对类型进行转换,代码可读性,可维护 ...
- 使用阿里云Code进行版本控制并配置IDEA
1. 申请阿里code的账号,网址如下https://code.aliyun.com, 2. 申请完成之后,将账号信息发给项目负责人,由负责人加入项目中 3. 下载git,下载地址为 ...
- 剑指offer-第六章面试中的各项能力(n个骰子的点数)
题目:把n个骰子扔到地上,骰子之和为S,输入n,打印s所有可能的值出现的概率. 思路:由于骰子的点数为1~6,因此n个骰子之和的大小为n~6n之间.故可以定义一个数组来存放这6n-n+1个数出现的次数 ...
- volley源码解析-Throwable类源码解析
前提知识点: 1.Serializable接口 作用:表示可序列化的语义.就是Java提供的通用数据保存和读取接口.任何类型实现了Serializeable接口,就可以被保存到文件中,或者作为数据流通 ...
- lvds配置
基于Altera FPGA的LVDS配置应用一例 在特权同学发表博文<Cyclone III的LVDS接口注意事项>后,不少网友发邮件询问LVDS具体应用的一些问题.这些网友,归根到底,估 ...
- Python的Django框架中if标签的相关使用
{% if today_is_weekend%} {% end if %} 系统会显示在这之间的内容 {% else %}标签是可选的 在python和django模板系统中,以下对象相当于布尔值的F ...