Windows环境下Unicode编程总结Word格式.docx
- 文档编号:16556527
- 上传时间:2022-11-24
- 格式:DOCX
- 页数:9
- 大小:21.87KB
Windows环境下Unicode编程总结Word格式.docx
《Windows环境下Unicode编程总结Word格式.docx》由会员分享,可在线阅读,更多相关《Windows环境下Unicode编程总结Word格式.docx(9页珍藏版)》请在冰豆网上搜索。
windows2000是使用unicode从头进行开发的,如果调用任何一个windows函数并给它传递一个ansi字符串,那幺系统首先要将字符串转换成unicode,然后将unicode字符串传递给操作系统。
如果希望函数返回ansi字符串,系统就会首先将unicode字符串转换成ansi字符串,然后将结果返回给你的应用程序。
进行这些字符串的转换需要占用系统的时间和内存。
通过从头开始用unicode来开发应用程序,就能够使你的应用程序更加有效地运行。
windowsce本身就是使用unicode的一种操作系统,完全不支持ansiwindows函数
windows98只支持ansi,只能为ansi开发应用程序。
microsoft公司将com从16位windows转换成win32时,公司决定需要字符串的所有com接口方法都只能接受unicode字符串。
4.如何编写unicode源代码?
microsoft公司为unicode设计了windowsapi,这样,可以尽量减少代码的影响。
实际上,可以编写单个源代码文件,以便使用或者不使用unicode来对它进行编译。
只需要定义两个宏(unicode和_unicode),就可以修改然后重新编译该源文件。
_unicode宏用于c运行期头文件,而unicode宏则用于windows头文件。
当编译源代码模块时,通常必须同时定义这两个宏。
5.windows定义的unicode数据类型有哪些?
数据类型说明
wcharunicode字符
pwstr指向unicode字符串的指针
pcwstr指向一个恒定的unicode字符串的指针
对应的ansi数据类型为char,lpstr和lpcstr。
ansi/unicode通用数据类型为tchar,ptstr,lpctstr。
6.如何对unicode进行操作?
字符集特性实例
ansi操作函数以str开头strcpy
unicode操作函数以wcs开头wcscpy
mbcs操作函数以_mbs开头_mbscpy
ansi/unicode操作函数以_tcs开头_tcscpy(c运行期库)
ansi/unicode操作函数以lstr开头lstrcpy(windows函数)
所有新的和未过时的函数在windows2000中都同时拥有ansi和unicode两个版本。
ansi版本函数结尾以a表示;
unicode版本函数结尾以w表示。
windows会如下定义:
#ifdefunicode
#definecreatewindowexcreatewindowexw
#else
#definecreatewindowexcreatewindowexa
#endif//!
unicode
7.如何表示unicode字符串常量?
字符集实例
ansi“string”
unicodel“string”
ansi/unicodet(“string”)或_text(“string”)if(szerror[0]==_text(‘j’)){}
8.为什幺应当尽量使用操作系统函数?
这将有助于稍稍提高应用程序的运行性能,因为操作系统字符串函数常常被大型应用程序比如操作系统的外壳进程explorer.exe所使用。
由于这些函数使用得很多,因此,在应用程序运行时,它们可能已经被装入ram。
如:
strcat,strchr,strcmp和strcpy等。
9.如何编写符合ansi和unicode的应用程序?
(1)将文本串视为字符数组,而不是chars数组或字节数组。
(2)将通用数据类型(如tchar和ptstr)用于文本字符和字符串。
(3)将显式数据类型(如byte和pbyte)用于字节、字节指针和数据缓存。
(4)将text宏用于原义字符和字符串。
(5)执行全局性替换(例如用ptstr替换pstr)。
(6)修改字符串运算问题。
例如函数通常希望在字符中传递一个缓存的大小,而不是字节。
这意味着不应该传递sizeof(szbuffer),而应该传递(sizeof(szbuffer)/sizeof(tchar)。
另外,如果需要为字符串分配一个内存块,并且拥有该字符串中的字符数目,那幺请记住要按字节来分配内存。
这就是说,应该调用
malloc(ncharacters*sizeof(tchar)),而不是调用malloc(ncharacters)。
10.如何对字符串进行有选择的比较?
通过调用comparestring来实现。
标志含义
norm_ignorecase忽略字母的大小写
norm_ignorekanatype不区分平假名与片假名字符
norm_ignorenonspace忽略无间隔字符
norm_ignoresymbols忽略符号
norm_ignorewidth不区分单字节字符与作为双字节字符的同一个字符
sort_stringsort将标点符号作为普通符号来处理
11.如何判断一个文本文件是ansi还是unicode?
判断如果文本文件的开头两个字节是0xff和0xfe,那幺就是unicode,否则是ansi。
12.如何判断一段字符串是ansi还是unicode?
用istextunicode进行判断。
istextunicode使用一系列统计方法和定性方法,以便猜测缓存的内容。
由于这不是一种确切的科学方法,因此istextunicode有可能返回不正确的结果。
13.如何在unicode与ansi之间转换字符串?
windows函数multibytetowidechar用于将多字节字符串转换成宽字符串;
函数widechartomultibyte将宽字符串转换成等价的多字节字符串。
MultiByteToWideChar的与WideCharToMultiByte的参数详解
第一个就是宽字符到多字节字符转换函数,函数原型如下:
intWideCharToMultiByte(
UINTCodePage,
DWORDdwFlags,
LPCWSTRlpWideCharStr,
intcchWideChar,
LPSTRlpMultiByteStr,
intcbMultiByte,
LPCSTRlpDefaultChar,
LPBOOLlpUsedDefaultChar
);
此函数把宽字符串转换成指定的新的字符串,如ANSI,UTF8等,新字符串不必是多字节字符集。
参数:
CodePage:
指定要转换成的字符集代码页,它可以是任何已经安装的或系统自带的字符集,你也可以使用如下所示代码页之一。
CP_ACP当前系统ANSI代码页
CP_MACCP当前系统Macintosh代码页
CP_OEMCP当前系统OEM代码页,一种原始设备制造商硬件扫描码
CP_SYMBOLSymbol代码页,用于Windows2000及以后版本,我不明白是什么
CP_THREAD_ACP当前线程ANSI代码页,用于Windows2000及以后版本,我不明白是什么
CP_UTF7UTF-7,设置此值时lpDefaultChar和lpUsedDefaultChar都必须为NULL
CP_UTF8UTF-8,设置此值时lpDefaultChar和lpUsedDefaultChar都必须为NULL
我想最常用的应该是CP_ACP和CP_UTF8了,前者将宽字符转换为ANSI,后者转换为UTF8。
dwFlags:
指定如何处理没有转换的字符,但不设此参数函数会运行的更快一些,我都是把它设为0。
可设的值如下表所示:
WC_NO_BEST_FIT_CHARS把不能直接转换成相应多字节字符的Unicode字符转换成lpDefaultChar指定的默认字符。
也就是说,如果把Unicode转换成多字节字符,然后再转换回来,你并不一定得到相同的Unicode字符,因为这期间可能使用了默认字符。
此选项可以单独使用,也可以和其他选项一起使用。
WC_COMPOSITECHECK把合成字符转换成预制的字符。
它可以与后三个选项中的任何一个组合使用,如果没有与他们中的任何一个组合,则与选项WC_SEPCHARS相同。
WC_ERR_INVALID_CHARS此选项会致使函数遇到无效字符时失败返回,并且GetLastError会返回错误码ERROR_NO_UNICODE_TRANSLATION。
否则函数会自动丢弃非法字符。
此选项只能用于UTF8。
WC_DISCARDNS转换时丢弃不占空间的字符,与WC_COMPOSITECHECK一起使用
WC_SEPCHARS转换时产生单独的字符,此是默认转换选项,与WC_COMPOSITECHECK一起使用
WC_DEFAULTCHAR转换时使用默认字符代替例外的字符,(最常见的如’?
’),与WC_COMPOSITECHECK一起使用。
当指定WC_COMPOSITECHECK时,函数会将合成字符转换成预制字符。
合成字符由一个基字符和一个不占空间的字符(如欧洲国家及汉语拼音的音标)组成,每一个都有不同的字符值。
预制字符有一个用于表示基字符和不占空间字符的合成体的单一的字符值。
当指定WC_COMPOSITECHECK选项时,也可以使用上表列出的最后3个选项来定制预制字符的转换规则。
这些选项决定了函数在遇到宽字符串的合成字符没有对应的预制字符时的行为,他们与WC_COMPOSITECHECK一起使用,如果都没有指定,函数默认WC_SEPCHARS。
对于下列代码页,dwFlags必须为0,否则函数返回错误码ERROR_INVALID_FLAGS。
502205022150222502255022750229529365493657002到5701165000(UTF7)42(Symbol)
对于UTF8,dwFlags必须为0或WC_ERR_INVALID_CHARS,否则函数都将失败返回并设置错误码ERROR_INVALID_FLAGS,你可以调用GetLastError获得。
lpWideCharStr:
待转换的宽字符串。
cchWideChar:
待转换宽字符串的长度,-1表示转换到字符串结尾。
lpMultiByteStr:
接收转换后输出新串的缓冲区。
cbMultiByte:
输出缓冲区大小,如果为0,lpMultiByteStr将被忽略,函数将返回所需缓冲区大小而不使用lpMultiByteStr。
lpDefaultChar:
指向字符的指针,在指定编码里找不到相应字符时使用此字符作为默认字符代替。
如果为NULL则使用系统默认字符。
对于要求此参数为NULL的dwFlags而使用此参数,函数将失败返回并设置错误码ERROR_INVALID_PARAMETER。
lpUsedDefaultChar:
开关变量的指针,用以表明是否使用过默认字符。
lpDefaultChar和lpUsedDefaultChar都设为NULL,函数会更快一些。
返回值:
如果函数成功,且cbMultiByte非0,返回写入lpMultiByteStr的字节数(包括字符串结尾的null);
cbMultiByte为0,则返回转换所需
字节数。
函数失败,返回0。
注意:
函数WideCharToMultiByte使用不当,会给影响程序的安全。
调用此函数会很容易导致内存泄漏,因为lpWideCharStr指向的输入缓冲区大小是宽字符数,而lpMultiByteStr指向的输出缓冲区大小是字节数。
为了避免内存泄漏,应确保为输出缓冲区指定合适的大小。
我的方法是先使cbMultiByte为0调用WideCharToMultiByte一次以获得所需缓冲区大小,为缓冲区分配空间,然后再次调用WideCharToMultiByte填充缓冲区,详见下面的代码。
另外,从UnicodeUTF16向非Unicode字符集转换可能会导致数据丢失,因为该字符集可能无法找到表示特定Unicode数据的字符。
wchar_t*pwszUnicode="
Holle,word!
你好,中国!
"
;
intiSize;
char*pszMultiByte;
iSize=WideCharToMultiByte(CP_ACP,0,pwszUnicode,-1,NULL,0,NULL,NULL);
pszMultiByte=(char*)malloc((iSize+1)/**sizeof(char)*/);
WideCharToMultiByte(CP_ACP,0,pwszUnicode,-1,pszMultiByte,iSize,NULL,NULL);
第二个是多字节字符到宽字符转换函数,函数原型如下:
>
intMultiByteToWideChar(
LPCSTRlpMultiByteStr,
LPWSTRlpWideCharStr,
intcchWideChar
此函数把多字节字符串转换成宽字符串(Unicode),待转换的字符串并不一定是多字节的。
此函数的参数,返回值及注意事项参见上面函数WideCharToMultiByte的说明,这里只对dwFlags做简单解释。
指定是否转换成预制字符或合成的宽字符,对控制字符是否使用像形文字,以及怎样处理无效字符。
MB_PRECOMPOSED总是使用预制字符,即有单个预制字符时,就不会使用分解的基字符和不占空间字符。
此为函数的默认选项,不能和MB_COMPOSITE合用
MB_COMPOSITE总是使用分解字符,即总是使用基字符+不占空间字符的方式
MB_ERR_INVALID_CHARS设置此选项,函数遇到非法字符就失败并返回错误码ERROR_NO_UNICODE_TRANSLATION,否则丢弃非法字符
MB_USEGLYPHCHARS使用像形字符代替控制字符
对于UTF8,dwFlags必须为0或MB_ERR_INVALID_CHARS,否则函数都将失败并返回错误码ERROR_INVALID_FLAGS。
以下函数我没用过,只简要说明之。
intGetTextCharset(HDChdc);
此函数获取当前选进的设备描述表的字符集,等同于GetTextCharsetInfo(hdc,NULL,0)。
成功返回字符集标识,失败返回DEFAULT_CHARSET。
ont-family:
couriernew"
mso-hansi-font-family:
mso-bidi-font-family:
"
低128位仍然存放原来的ascii码,
而高128位加入了希腊字母等
ifdefunicode
tchar=wchar
else
tchar=char
你需要在project\settings\c/c++\preprocesserdefinitions中添加unicode和_unicode
uincode,_unicode都要定义。
不定义_unicode的话,用settext(hwnd,lpctstr),将被解释为settexta(hwnd,lptstr),这时api将把你给的unicode字符串看作ansi字符串,显示乱码。
因为windowsapi是已经编译好存在于dll中的,由于不管unicode还是ansi字符串,都被看作一段buffer,如"
0ba30035243c0000"
如果按ansi读,因为ansi字串是以'
\0'
结束的,所以只能读到两字节"
0ba3\0"
,如果按unicode读,将完整的读到'
\0\0'
ily:
结束。
由于unicode没有额外的指示位,所以系统必须知道你提供的字串是哪种格式。
此外,unicode好象是ansic++规定的,_unicode是windowssdk提供的。
如果不编写windows程序,可以只定义unicode。
开发过程:
围绕着文件读写、字符串处理展开。
文件主要有两种:
.txt和.ini文件
在unicode和非unicode环境下字符串做不同处理的,那么需要参考以上9,10两条,以适应不同环境得字符串处理要求。
对文件读写也一样。
只要调用相关接口函数时,参数中的字符串前都加上_text等相关宏。
如果写成的那个文件需要是unicode格式保存的,那么在创建文件时需要加入一个字节头。
cfilefile;
wcharszwbuffer[128];
wchar*pszunicode=l"
unicodestring\n"
//unicodestring
char*pszansi="
ansistring\n"
//ansistring
wordwsignature=0xfeff;
file.open(text("
test.txt"
),cfile:
:
modecreate|cfile:
modewrite);
file.write(&
wsignature,2);
file.write(pszunicode,lstrlenw(pszunicode)*sizeof(wchar));
//explicitlyuselstrlenwfunction
multibytetowidechar(cp_acp,0,pszansi,-1,szwbuffer,128);
file.write(szwbuffer,lstrlenw(szwbuffer)*sizeof(wchar));
file.close();
//以上这段代码在unicode和非unicode环境下都有效。
这里显式的指明用unicode来进行操作。
2.
在非unicode环境下,缺省调用的都是ansi格式的字符串,此时tchar转换为char类型的,除非显式定义wchar。
所以在这个环境下,如果读取unicode文件,那么首先需要移动2个字节,然后读取得字符串需要用multibytetowidechar来转换,转换后字符串信息才代表unicode数据。
在unicode环境下,缺省调用得都是unicode格式得字符串,也就是宽字符,此时tchar转换为wchar,相关得api函数也都调用宽字符类型的函数。
此时读取unicode文件也和上面一样,但是读取得数据是wchar的,如果要转换成ansi格式,需要调用widechartomultibyte。
如果读取ansi的,则不用移动两个字节,直接读取然后视需要转换即可。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Windows 环境 Unicode 编程 总结