飘雪

C++博客 首页 新随笔 联系 聚合 管理
  31 Posts :: 0 Stories :: 60 Comments :: 0 Trackbacks
    最近在做嵌入式开发,这个嵌入式平台上,支持标准c库,但不支持mbcs,也不支持unicode。里面的wchar_t被直接定义为char(typedef char wchar_t;),可见这个wchar_t是假的,只是为了让含有wchar_t的程序能通过编译,并不是支持unicode,当然也就没有对应的wcs函数族。现在要让这个系统上的程序支持中文,有下面几种想法。
    首先要弄清支持中文的含义,先分析一下需求,这个程序对字符串的操作主要是如下流程,从文件中读进字符串(文件编码可自己定义),对字符串进行查找、截取、拼接操作,最后把完成的字符串作为参数传到另一个库里(暂且叫它libn吧)。需要说明的是,libn由公司别的小组实现,它不关注字符集,里面不再处理(截取、拼接)字符串,只是把输入的字符串输出到文件或屏幕,目前已经有一个比较稳定的跨平台版本。
    需求确定以后,接下来要确定中文在程序中的存储编码。对中文来说,通常有三种编码方案可供选择:
    1. 用mbcs编码存储(gb2312/gbk/gb18030)。
    2. 用unicode编码存储。
    3. 用utf-8编码存储。
    这个系统里针对这三种编码的字符串函数都没有,不管采用哪种方案,字符串函数都得自己写,从这点来说,三种方案的工作量都差不多。
    先来看看mbcs,这个方案纯粹是为了中文而支持中文,如果将来要兼容其他语言,mbcs函数都得重写,而且mbcs跟unicode的转换没有固定的公式,必须依赖于一张大表。用mbcs没有什么特别的好处,这个方案只能早早的就否决了。
    再来看看unicode和utf-8。一般说来,unicode是国际化的终极解决方案,大部分c编译器支持wchar_t数据类型,如果编译器不支持wchar_t,可以自己使用unsigned short或unsigned int来模拟。不管什么语言,每个字符都被放到2字节的wchar_t类型里(linux下是4字节),通常对于新的程序,都推荐使用unicode。而utf-8是unicode的一种存储方案。
    下面我们从不同方面来比较一下unicode和utf-8各自的优势:
    1. 内存空间。unicode对于每个字符都是2个字节,utf-8对英文是一个字节,对汉字是2个或3个字节。对于英文来说,utf-8占优,但在汉字占多数的情况下,unicode占优势。当然,如果字符串的数量不是很大的话,这个问题不是很突出。这里列出来,对文件存储也可以起到一个参考作用。
    2. 程序编写难度。unicode是定长类型,而utf-8是变长的,每操作一个字符的时候,都要考虑这个字符的长度,毫无疑问unicode的字符串函数编写起来应该更简单。目前,这两种字符串函数都有大量的实现可供参考,对于写程序来说,问题不大。
    3. 程序执行效率。unicode定长,utf-8变长。对于strlen,substr之类的操作,unicode很方便,utf-8却要从头到尾扫描,而且需要边扫描边判断字符长度。因此unicode比utf-8要快很多,但如果这种操作不是很多,效率影响也不会特别明显。
    4. 现有程序的数量。unicode程序我们见得多了,但采用utf-8的程序也不少,gtk+就是。它们都运行得很好。
    5. 兼容性。英文的utf-8编码跟ascii完全一样,因此也兼容标准c库的字符串函数,如果不需要操作字符,完全不用关心语言。对于unicode,标准c库的字符串函数不能工作,字符串函数都得重写,常常用一个宏来控制在unicode和ascii直接切换(比如windows下的TCHAR)。
    从上面几点来看,跟utf-8相比,unicode占据绝对优势。只有unicode的世界真美好...
    但事实上,libn因为它并不关心字符集,所以它把接口的字符串类型全部声明成char*了,如果libn也用unicode实现,那就完美了,可惜,这不在我的控制范围之内。
    另外还有一种方案,在我的程序内部使用unicode,在调用libn的接口处,转换成utf-8,传给libn,从libn返回的utf-8字符串,先转成unicode再使用。这个方法听起来也不错,但是很多对象并不是调用接口时才生成,也不是调用完就销毁,这样会导致我的程序内会长期存在字符串的unicode和utf-8两种拷贝,浪费大量内存,对于嵌入式系统来说,这很难容忍。
    最终,我决定在我的程序内部使用utf-8编码,作出这个决定的最主要原因是因为我要使用libn,虽然这样我的程序会消耗更多的内存、需要编写冗长难懂的字符串函数、效率也会下降,但不得不这样。gtk+没有使用unicode而采用utf-8,恐怕也是这样妥协的结果吧。
    后记:utf-8函数参考了glib中的实现。



posted on 2009-02-17 15:44 飘雪 阅读(2123) 评论(13)  编辑 收藏 引用 所属分类: c/c++

Feedback

# re: 嵌入式系统的中文支持与国际化 2009-02-17 16:08 路人丁
你说的unicode其实特指UCS-2。
UCS-2 和 utf-8 相比较,自然是选 utf-8

"c编译器支持wchar_t数据类型" --- wchar_t在C/C++是宽字符,而没有规定宽字符必须是ucs-2编码,VC的wchar_t是用ucs2编码,而其他编译器大部分用ucs4编码。  回复  更多评论
  

# re: 嵌入式系统的中文支持与国际化 2009-02-17 16:16 飘雪
@路人丁
你说的很对,我上面也注明了“linux下是4字节”,不过没有具体说ucs-2或ucs-4,另外我也提到了在没有wchar_t支持的情况下,用short或int来模拟,其实说的也是这个问题

因为我的程序主要是嵌入式系统,所以几乎肯定不会考虑ucs-4,这个是我没说清楚语境  回复  更多评论
  

# re: 嵌入式系统的中文支持与国际化 2009-02-17 16:20 飘雪
@路人丁
另外你说的“UCS-2 和 utf-8 相比较,自然是选 utf-8 ”
这个我不这么认为,如果不是要使用别人的库,我肯定不会考虑utf-8的  回复  更多评论
  

# re: 嵌入式系统的中文支持与国际化 2009-02-17 17:47 路人丁
utf-8也是unicode的一种编码,“unicode比utf-8要快很多”的说法不够严谨。  回复  更多评论
  

# re: 嵌入式系统的中文支持与国际化 2009-02-17 17:48 路人丙
上面的一条是“路人丙”回的,路人丙道歉。  回复  更多评论
  

# re: 嵌入式系统的中文支持与国际化 2009-02-17 17:51 路人丙
一直没搞懂,Windows使用UTF-16,超过UNICODE编码中两个字节编码范围的汉字是怎么处理的。  回复  更多评论
  

# re: 嵌入式系统的中文支持与国际化 2009-02-17 18:06 飘雪
@路人丁
utf-8也是unicode的一种编码,“unicode比utf-8要快很多”的说法不够严谨

我本来想说的是处理直接用unicode(ucs-2)存储的字符串比处理用utf-8存储的字符串快得多,表达不够清楚  回复  更多评论
  

# re: 嵌入式系统的中文支持与国际化 2009-02-17 20:49 路人戊
好奇那个libn是什么,为何能够不依赖编码。毕竟mbcs和utf8结构上差别还是挺大的。如果只是写成char*来拿raw data的话,直接把unsigned short*转成char*不行么……  回复  更多评论
  

# re: 嵌入式系统的中文支持与国际化 2009-02-18 05:52 路人乙
@路人丙
还要再查表,对于某些超出unicode编码范围的字符,内存里的其实是外表的表id和表内索引,去那个外表再取字。  回复  更多评论
  

# re: 嵌入式系统的中文支持与国际化 2009-02-18 11:06 飘雪
好奇那个libn是什么,为何能够不依赖编码。毕竟mbcs和utf8结构上差别还是挺大的。如果只是写成char*来拿raw data的话,直接把unsigned short*转成char*不行么……


libn对于字符串的处理很简单,不做substr之类的操作,实际上里面用得最多的可能是strcmp,只比较字符串,这样的话utf-8能正常工作,unsigned short就不能工作了  回复  更多评论
  

# re: 嵌入式系统的中文支持与国际化 2009-02-23 17:21 Agaric
@路人丙
UTF16不一定是"双字节"。

代码点存在于“代码空间”中。代码空间由许多标量值组成,这些值被划分在两个平面中:

基本多语种平面(64k 大小)。
在 Unicode 中,此下平面中的值的十六进制表示位于 U+0000 到 U+FFFF 的范围中。

辅助多语种平面(16 个 64k 大小的附加节)。
在 Unicode 中,此上平面中的值的十六进制表示位于 U+10000 到 U+10FFFF 的范围中。
  回复  更多评论
  

# re: 嵌入式系统的中文支持与国际化 2009-03-05 12:04 飘雪
@路人丙
一直没搞懂,Windows使用UTF-16,超过UNICODE编码中两个字节编码范围的汉字是怎么处理的。

可参看 http://www.ietf.org/rfc/rfc2781.txt,
rfc2279: UTF-8, a transformation format of ISO 10646
  回复  更多评论
  

# re: 嵌入式系统的中文支持与国际化 2009-03-05 12:04 飘雪
@路人丙
一直没搞懂,Windows使用UTF-16,超过UNICODE编码中两个字节编码范围的汉字是怎么处理的。

可参看 http://www.ietf.org/rfc/rfc2781.txt,
rfc2781: UTF-16, an encoding of ISO 10646

  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理