您的位置:首页 > 编程语言 > C语言/C++

跨平台C++软件开发中,由于不同操作系统对Unicode的支持差异,而导致的一些问题及解决方案。

2004-10-16 19:10 911 查看
1. 问题的提出。

各种各样的编码永远是软件开发者最为头痛的问题之一,Unicode为统一编码带来了希望。可是,就算是Unicode也不是百分百的完美,它只是完成了对各种语言编码的制定,而在具体的操作系统支持上,又分为UTF8,UTF16和UTF32好几个版本。比如,Windows系统支持的Unicode是UTF16,也就是每2个字节表示一个字符(还有一种称为代理的情况,容后讨论)。而Linux下默认支持的却是UTF32的Unicode标准,每4个字节才表示一个字符。

2. 实例说明

想象一下,假设您在Windows 系统下开发了一个软件,将一些文本数据用Unicode(UTF16)编码保存到一个文件,现在由于业务需要,您想将这个程序在Linux平台跑起来,会发生什么情况呢?

一般来说,您的代码在处理字符串资源时,会使用C/C++标准库的wchar_t数组或者std::wstring来保存字符串,使用wstrcpy,wstrlen或者std::string类提供的成员函数处理字符串,然后使用wfprintf或者std::wfstream进行字符串的读写。这部分代码好像没有问题,标准的C/C++ 函数,在整个软件移植时都不用修改。是的,代码词法和语法确实都没有问题,编译也能够通过。可是,程序运行的结果呢?根据上面的讨论,wchar_t在Windows平台下,,每个字符2个字节;而在linux平台下,每个字符4个字节。如果您的某个用户在Windows平台下保存一个字符串“Hello”到某个文件,然后另一个用户在Linux下打开这个文件,那么,他所得到会是什么呢?
Windows平台下用Unicode(UTF16)编码保存“Hello“到文件,实际写入的16进制串如下所示
H e l l o
4800 6500 6C00 6C00 6F00
形成一个串,00480065006C006C006F,写入文件。
在Linux系统下,程序将这个串当作UTF32读入后,结果是两个字符(最后2个字节6F00被舍弃)
0x00650048和0x006C006C,字符串长度是2,这显然不是希望的到的“Hello“。

3. 解决的办法

根据个人的经验,解决方案主要有以下2种:

1. 由于产生平台不兼容的主要原因是平台之间使用的Unicode方案不统一,一个最为显而易见的解决办法就是选择使用某种操作系统的编码,在另一个平台上,使用自己的字符串保存和操作函数。一般推荐使用UTF16,具体原因请参考本人关于UTF16和UTF32的比较。决定好使用的编码方案后,还需要定义相应的操作函数,如字符串拷贝函数,比较函数等。一个偷懒的办法是把VC crt的部分代码Copy出来,什么wstrcpy,wstrlen,一个也不放过。在程序中进行字符串处理和存取时使用自己定义的方法,就可以避免平台差异带来的问题了。
而且,选择这种方案的一个更为重要的原因是,这个解决方案已经有大量的Open Source软件库可以直接使用,比如ICU(International Component for Unicode),libiconv等。

2. 避开UTF16和UTF32,直接使用UTF8进行字符串的处理,因为各个平台对于UTF8的处理都是完全相同的。而且,UTF8和UTF16和UTF32使用的编码完全一样,只是内存表示的差异,有成熟的算法可以实现这3种编码的直接转换.以下是www.unicode.org官方的转换代码连接:http://www.unicode.org/Public/PROGRAMS/CVTUTF/
当然,这种做法也有一定的不利因素,因为UTF8本身是一种可变长的编码方案,对于常见的英文,使用一个字节,对于中文,一般是3个字节。这种可变长的字符编码给一些操作带来不便。如取某个字符串的子串,就必须从头开始做遍历,然后一个一个字符进行计算,直到长度达到要求。而如果使用UTF16或者UTF32,简单的对数组进行索引就可以了(不考虑UTF16的代理机制,常见文字不会用到)。

关于UTF8,UTF16,UTF32的详细讨论可以参考www.unicode.org,也可以参考本人blog编码文件夹下的一些介绍性文字

4. 参考文档
www.unicode.org,本文提及的所有资料都可以在unicode.org上找到。
http://oss.software.ibm.com/icu/,IBM的开源Unicode实现,可以完全替代操作系统提供的与编码和国际化相关的功能。
http://www.gnu.org/software/libiconv/, GNU的Unicode实现,集成在Linux操作系统中,但是库本身跨平台。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐