织梦CMS - 轻松建站从此开始!

罗索

汉字编码及LINUX中文处理

jackyhwei 发布于 2010-11-22 10:36 点击:次 
Linux 下的汉字编码是以UTF-8,这从RHEL的中文版的语言就可以知道,中文环境下,环境变量LANG的值为 zh_CN.UTF8,而WINDOWS自WINDOWS NT开始,内部都采用UNICODE表示.因此两者在编程有着细微差别.
TAG:

字符编码类型
 
英文字符,使用ASCII,用一个byte表示即可.ASCII码一共规定了128个字符的编码,比如空格“SPACE”是32(二进制 00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7 位,最前面的1位统一规定为0。
汉字用一个byte来表示明显不够,因此最早的汉字编码,是采用两个byte来表示.同时为了与原来ascii英文字符不混淆.特别规定:
两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到 0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,我们还把数学符号、罗马希腊的 字母、日文的假名们都编进去了,连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。 这个方案称为GB2312编码.一般称为国标码.
在计算机在中国开始普及年代,如DOS/WIN3.1/win95等阶段.GB2312立下了汗马功劳.在同一时期,以繁体字为主的台湾也搞一套类似的编码,称为BIG5编码.原理是一样的,但是与GB2312码有冲突.
 
但是GB2312.还有很多缺点,一是字符集太小,只能表示几千个常用汉字.大量汉字没法表示,二是其它汉字表示集BIG5有冲突,经常出现乱码的情况.三是如果出现几种文字需要同时显示,如阿拉伯文,泰文等无法实现.这种情况在互联网时代尤其明显.
 
UNICODE
 
为了解决全世界文字冲突问题,ISO把所有常用语言的字符,全部统一编码,称为"Universal Multiple-Octet Coded Character Set",简称 UCS,或称UNICODE方案.
它规定所有字符包括英文字符由2个字节表示.但为了的兼容.原来的ASCII码高位字节全部采用0,低位就是原来ASCII值. 
   
需要注意的是,Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。我们一般称为UNICODE表示,是 指用两个byte来,即一个Short来表示的方法.2个字节在32位CPU上正好是一个short型,这样在不同字节序的CPU下,同一个编码有两种排 序,默认是小端字节序.也有按大端字节序,两种方案分别称为 Unicode,Unicode-Big.
这样就造成一个编码有多种存储方式,这样造成推广的不便.
 
UNICODE 在制订时没有考虑与任何一种现有的编码方案保持兼容,这使得 GBK 与UNICODE 在汉字的内码编排上完全是不一样的,没有一种简单的算术方法可以把文本内容从UNICODE编码和另一种编码进行转换,这种转换必须通过查表来进行.

  

UTF-8
随着互联网兴起,如何在网络上传输字符UNICODE也是一个问题.于是面向传输的众多 UTF(UCS Transfer Format)标准出现了,顾名思义,UTF8就是每次8个位传输数据,而 UTF16就是每次16个位,

UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

UTF-8的编码规则很简单,只有二条:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。

2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

下表总结了编码规则,字母x表示可用编码的位。

Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

下面,还是以汉字“严”为例,演示如何实现UTF-8编码。

已知“严”的unicode是4E25(100111000100101),根据上表,可以发现 4E25处在第三行的范围内(0000 0800-0000 FFFF),因此“严”的UTF-8编码需要三个字节,即格式是“1110xxxx 10xxxxxx 10xxxxxx”。然后,从“严”的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,“严”的UTF-8编码是 “11100100 10111000 10100101”,转换成十六进制就是E4B8A5。

 
GBK
GBK编码(Chinese Internal Code Specification)是中国大陆制订的、等同于UCS的新的中文编码扩展国家标准。gbk编码能够用来同时表示繁体字和简体字,而gb2312只 能表示简体字,gbk是兼容gb2312编码的。GBK工作小组于1995年10月,同年12月完成GBK规范。该编码标准兼容GB2312,共收录汉字 21003个、符号883个,并提供1894个造字码位,简、繁体字融于一库。Windows95/98简体中文版的字库表层编码就采用的是GBK,通过 GBK与UCS之间一一对应的码表与底层字库联系。
 
一般有时把ASCII与GB2312混排称为ANSI,它与UTF-8,UNICODE,UNICODE BIG称为四种编码.
 
WINDOW的记事本支持四种编码汉字
  
 
 
文本文件类型
因为并存好几种编码,软件处理文本文件是如何判断类型的?实际如果不加一些附加信息,软件也难判断文本是哪一种格式.一般是文件前面加入BOM(Byte Order Mark)码.其中有下表.
Bytes Encoding Form
00 00 FE FF        UTF-32, big-endian
FF FE 00 00        UTF-32, little-endian
FE FF        UTF-16, big-endian/即一般的UNICODE-BIG
FF FE        UTF-16, little-endian/即UNICODE
EF BB BF        UTF-8
 
这样只要打开文本文件内容,查看0-3 byte是否这一些数字,即判断出是哪一种格式.如果全部都不是,意味着是ANSI编码.
 
关于BOM,更详细参见
 
一些编码格式一般是约定成俗的,如*.lrc,往往使用ASCII与GB码混排,即ANIS格式.C源程序采用ASCII.但中间的汉字在不同系统下有不同规定LINUX采用UTF-8,WINDOWS采用GB码.
 
Windows/Unix 文本回车符.
 
处理文本文件还有一个细节,是WINDOWS的每行回车符两个字符,\r\n,而UNIX回车符一个字符是\n,而它还有一个特殊规定,最后一行是空行, 即\n\n结尾.大部分软件能识别两种格式,但是WINDOWS记事本打开LINUX文本文件时,并不换行而是显示黑框.
但fgets之类实现是最早在UNIX实现,所有读出来最后的字符都是\n,WINDOWS上也是如此.必须用fopen(name,"rb")然后用fread才能读出\r\n来.
  
标装C宽字节类型
  strlen(),计算结果只针对ASCII有效,对于2个BYTE字节无法处理.因此标准C中,制定了wchar_t,它一般被定义成unsigned short 型.对宽字节的函数要采用新的w打头的接口.
如求宽字符字符串的长度的函数是
#include <wchar.h>
size_t wcslen(const wchar_t *s);
 
Linux 下汉字处理
 
   Linux 下的汉字编码是以UTF-8,这从RHEL的中文版的语言就可以知道,中文环境下,环境变量LANG的值为 zh_CN.UTF8,而WINDOWS自WINDOWS NT开始,内部都采用UNICODE表示.因此两者在编程有着细微差别.
   如果是带汉字的文本可参考相应的BOM来处理.但是在显示,打印时要因应不同的系统采用不同格式.
   如LINUX下控制台下,需要UTF-8格式才能正确处理.象SDL的图形界面下,汉字要转成UNICODE或UTF-8才能正常显示.文本文件还好处理.
   但如果在C代码里出现汉字常量
   如printf("黄新宇\n");,这个有不同的情况.如果这个C代码是在LINUX编辑,则C源程序中是UTF-8直接可以显示,如果这个C代码是在WINDOWS编辑拷贝过来.则很有可能是GB码,这样程序编译后在LINUX控制台上乱码.
  putty 下汉字显示,需要将字体换成UTF-8才能正常显示
 
另外LINUX中文文件名也是UTF-8编码的,可以在fopen中直接采用中文编码.如果WINDWOS的中文则有可能是UNICODE编码,但在samba拷贝后会自动转换
(Andrew Huang)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201011/10509.html]
本文出处:bluedrum.cublog.cn 作者:Andrew Huang
顶一下
(7)
87.5%
踩一下
(1)
12.5%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容