字符编码(续)---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) 编码规则:将「码位」转换为字节序列的规则(编码/ ...
随机推荐
- Android快速开发-选项卡
介绍 几行代码实现Android选项卡界面,支持标准底部Tab自定义视图选项卡,头部文字选项卡. 底部自定义视图选项卡 先来看看实现下图中的效果我们代码应该怎么写? 实现上图效果只需以下代码: pub ...
- ng 服务
服务的本质是单例对象,封装一些方法和属性的. 单例模式:在实例化变量的时候,如果该变量已经存在,直接返回该变量:如果不存在,就创建一个新的变量再返回 ng自带的服务有很多,常用:$location $ ...
- bzoj 4465 游戏中的学问
Written with StackEdit. Description 大家应该都见过很多人手拉手围着篝火跳舞的场景吧?一般情况下,大家手 拉手跳舞总是会围成一个大圈,每个人的左手拉着旁边朋友的右手, ...
- 微软原版WINDOWS10-LTSB-X64位操作系统的全新安装与优化
原版WINDOWS10_LTSB_X64位操作系统,安装U盘的制作 1.在一台能正常运行的电脑上,下载原版WINDOWS10_LTSB_X64位操作系统镜像(ISO)文件: 2.运行UltraISO. ...
- Vue.js devtool插件下载安装及后续问题解决
在中国,你是无法使用谷歌应用商店,所以你下载插件,要使用一些别的手段,一种是下载源码编译,另一种是通过第三方网站.第一种不适合小白,所以现在介绍第二组. 下载插件网站 国外网站:https://www ...
- Jmeter ----关于上传图片接口
转自:http://www.cnblogs.com/linglingyuese/p/4514808.html 需求 1 2 3 4 5 6 7 8 9 post上传 Request: { &quo ...
- 相对路径和绝对路径的区别,java获取项目访问路径的方法
相对路径和绝对路径的区别 在HTML里只要涉及文件的地方(如超级链接.图片等)就会涉及绝对路径与相对路径的概念. .绝对路径 绝对路径是指文件在硬盘上真正存在的路径.例如“bg.jpg”这个图片是存放 ...
- 安卓apk包重复签名问题
安卓数字签名指的是对apk包做文件摘要并加密,在安装apk包时做解密和验证以保证包体不被篡改.这里先普及下签名和验证流程.签名文件保存在apk包里META-INF目录下,包含3个文件: 1.后缀为MF ...
- RK3288 模块单独编译
模块以Email为例: 1.执行build目录下的脚本文件envsetup.sh $ source ./build/envsetup.sh 2.选择版本(user为用户版本 eng为工程版本) $ ...
- FIREDAC的心得
FIREDAC与UNIDAC有些不同 但大体上是相同的 以下是一些随手笔记: FieldCount是当前FDQuery2所在行里面有多少列 一般用FieldList[X]来代表第几列 str:=FDQ ...