C/C++ 编程中多国语言处理(2)

一般的编码转换,直接做映射的不太可能,需要比较多的工作量,大多情况下还是选择 Unicode 作为转换的中介。

使用库函数

如前文所说,JAVA 的 String 对象是以 Unicode 编码存在的,所以 JAVA 程序员主要关心的是读入时判断字节流的编码,从而确保可以正确的转化为 Unicode 编码;相比之下,C/C++ 将外部文件读出的数据存为字符数组、或者是 string 类型;而 wstring 才是符合 Unicode 编码的双字节数组。一般常用的方法是 C 标准库的 wcstombs、mbstowcs 函数,和 windows API 的 MultiByteToWideChar 与 WideCharToMultiByte 函数来完成向 Unicode 的转入和转出。

这里以 MBs2WCs 函数的实现说明 GB2312 向 Unicode 的转换的主要过程:


清单 1. 多字节字符串向宽字节字符串转换
wchar_t * MBs2WCs(const char* pszSrc){ wchar_t* pwcs = NULL; intsize = 0; #ifdefined(_linux_) setlocale(LC_ALL, "zh_CN.GB2312"); size = mbstowcs(NULL,pszSrc,0); pwcs = new wchar_t[size+1]; size = mbstowcs(pwcs, pszSrc, size+1); pwcs[size] = 0; #else size = MultiByteToWideChar(20936, 0, pszSrc, -1, 0, 0); if(size <= 0) returnNULL; pwcs = new wchar_t[size]; MultiByteToWideChar(20936, 0, pszSrc, -1, pwcs, size); #endif returnpwcs; }  

相应的,WCs2MBs 可以将宽字符串转化为字节流。


清单 2. 宽字节字符串向多字节字符串转换
char* WCs2MBs(const wchar_t * wcharStr){ char* str = NULL; intsize = 0; #ifdefined(_linux_) setlocale(LC_ALL, "zh_CN.UTF8"); size = wcstombs( NULL, wcharStr, 0); str = new char[size + 1]; wcstombs( str, wcharStr, size); str[size] = '\0'; #else size = WideCharToMultiByte( CP_UTF8, 0, wcharStr, -1, NULL, NULL, NULL, NULL ); str = new char[size]; WideCharToMultiByte( CP_UTF8, 0, wcharStr, -1, str, size, NULL, NULL ); #endif returnstr; }  

Linux 的 setlocale 的具体使用可以参阅有 C/C++ 文档,它关系到文字、货币单位、时间等很多格式问题。Windows 相关的代码中 20936 和宏定义 CP_UTF8 是 GB2312 编码对应的的 Code Page[ 类似的 Code Page 参数可以从 MSDN的 Encoding Class 有关信息中获得 ]。

这里需要特别指出的是 setlocale 的第二个参数,Linux 和 Windows 是不同的:

1. 笔者在 Eclipse CDT + MinGW 下使用 [country].[charset](如 zh_CN.gb2312 或 zh_CN.UTF8)的格式并不能通过编码转换测试,但可以使用 Code Page,即可以写成 setlocale(LC_ALL, ".20936") 这样的代码。这说明,这个参数与编译器无关,而与系统定义有关,而不同操作系统对于已安装字符集的定义是不同的。 2. Linux 系统下可以参见 /usr/lib/locale/ 路径,系统所支持的 locale 都在这里。转换成 UTF8 时,并不需要 [country] 部分一定是 zh_CN,en_US.UTF8 也可以正常转换。

另外,标准 C 和 Win32 API 函数返回值是不同的,标准 C 返回的 wchar_t 数组或者是 char 数组都没有字符串结束符,需要手动赋值,所以 Linux 部分的代码要有区别对待。

最后,还要注意应当在调用这两个函数后释放分配的空间。如果将 MBs2WCs 和 WCs2MBs 的返回值分别转化为 wstring 和 string,就可以在它们函数体内做 delete,这里为了代码简明,故而省略,但请读者别忘记。

第三方库

目前的第三方工具已经比较完善,这里介绍两个,本文侧重点不在此,不对其做太多探讨。

Linux 上存在第三方的 iconv 项目,使用也较为简单,其实质也是以 Unicode 作为转换的中介。可以参阅 iconv 相关网站。 ICU 是一个很完善的国际化工具。其中的 Code Page Conversion 功能也可以支持文本数据从任何字符集向 Unicode 的双向转换。可以访问其 网站

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwpzsd.html