Chinapromoter Blog

生活, 艺术, 网络, 技术, 工业, 消费, 记录趣味生活的点点滴滴。

« ASP+FSO生成的网页文件默认编码格式以及转换成UTF-8编码方法字符集Charset和文件编码Encoding的区别详解 »

网站编码Unicode、UTF-8、页面代码详解

做建站系统,程序要自动读取网页模板,并且在最后生成包含实际内容的网页。那么,读取网页模板时往往需要考虑“编码”问题。

编码问题只在保存文件、读取文件和网络传输过程中体现。也就是说,一段文字(比如汉字)存放在内存里是没有编码问题的,目前的操作系统内核一般都是UNICODE编码,也就是说,汉字也好、英文字母也好、数字也好,计算机都是当成双字节字符来处理的。当这些内容要写入文件、或者从文件读取、或者通过网络从一台机传输到另一台机时,才会发生UNICODE与其它编码的转换。

当从硬盘读取一个文件时,要判断它是什么编码,这样才可以真正从文件里提取出实际的内容。

ASCII

ASCII是一个美国标准,它不能满足其他国家的需要,例如斯拉夫语的字母和汉字,于是出现了Windows ANSI字符集,是一种扩展的ASCII码,用8位存放字符,低128位仍然存放原来的ASCII码,高128位加入了希腊字母等。

文件编码和网页编码

其实GB2312不是文件编码类型,而是网页编码类型。它只是表示网页里的汉字怎样解释。而文件本身,是ansi编码的。文件的编码比网页编码重要得多,因为要知道网页编码,先要能分析网页内容,而分析网页内容之前得先知道文件编码。

网页文件是ansi、unicode还是utf-8编码,如何判断文件编码类型?

一、检查BOM,只要用二进制方法读入两个字节看看即可。如果是FF FE或FE FF就是unicode编码。如果是EF BB BF就是utf-8,否则是ANSI,具体见下面清单。但是,utf-8文件不一定含BOM。如果也去检查BOM,会得出ansi的错误答案。

BOM(Byte order Mark)是一个字符,它表明UNICODE文本的UTF-16,UTF-32的编码字节顺序(高字节低字节顺序)和编码方式(UTF-8,UTF-16,UTF-32, 其中UTF-8编码是字节顺序无关的)。

用ADO.Stream,出现纰漏,用2进制工具查看生成的文件,发现前面多2个字节,FF FE.然后查了一下,原来是这样程序代码。

.Position = 2  '设置流对象的起始位置是2(过滤掉开始的一个控制字符
                     '这个控制字符是WriteText方法按默认属性Charset="Unicode" 
                     '读入数据的时候自动加到数据开头的,字符的值是FF3F 
                     '这个控制字符占2字节,所以Position设置为2 
                     '表示略过2个字节,下面的ReadText方法从Position开始读数据

二、分析文件内容,可是这个办法几乎是不太可行的。如果一个文件开头连续10000个ascii符号(英文字母、数字、空格),那你要分析到第几个字符才能结束?著名的UltraEdit就有这样的一个BUG。

第二个办法还有个大问题,符合1110xxxx 10xxxxxx 10xxxxxx格式的未必都是utf-8字符,它完全可能是一个半GBK编码。

如果规定每个文件都加BOM,结果如何?其实这也不是好办法。做网站技术的人可能研究过BOM,但是做美工的人可能根本不关心。要求合作伙伴去了解不属于他们认识范围的事物有点太不人道。更重要的是,如果做PHP的建站系统,PHP不支持BOM。

UTF-8: EF BB BF
UTF-16 : FF FE
UTF-16 big-endian: FE FF
UTF-32 little-endian: FF FE 00 00
UTF-32 big-endian: 00 00 FE FF

如何在Unicode与ANSI之间转换字符串

Windows函数MultiByteToWideChar用于将多字节字符串转换成宽字符串;函数WideCharToMultiByte将宽字符串转换成等价的多字节字符串。

目前常用的一些编码方案

1、在中国,大陆最常用的就是GBK18030编码,除此之外还有GBK,GB2312,这几个编码的关系是这样的。

最早制定的汉字编码是GB2312,包括6763个汉字和682个其它符号95年重新修订了编码,命名GBK1.0,共收录了21886个符号。之后又推出了GBK18030编码,共收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字,现在WINDOWS平台必需要支持GBK18030编码。

按照GBK18030、GBK、GB2312的顺序,3种编码是向下兼容,同一个汉字在三个编码方案中是相同的编码。

2、台湾,香港等地使用的是BIG5编码。

3、日本:SJIS编码。

如果把各种文字编码形容为各地的方言,那么Unicode就是世界各国合作开发的一种语言。在这种语言环境下,不会再有语言的编码冲突,在同屏下,可以显示任何语言的内容,这就是Unicode的最大好处。

Unicode编码方法

Unicode编码将世界上所有的文字用2个字节统一进行编码。2个字节最多能够表示65536个编码。

韩国和日本的大部分汉字都是从中国传播过去的,字型是完全一样的。比如:“文”字,GBK和SJIS中都是同一个汉字,只是编码不同而已。那样,像这样统一编码,2个字节就已经足够容纳世界上所有的语言的大部分文字。

Unicode的学名是"Universal Multiple-Octet Coded Character Set",简称为UCS。

现在用的是UCS-2,即2个字节编码,而UCS-4是为了防止将来2个字节不够用才开发的。UCS-2也称为基本多文种平面。UCS-2转换到UCS-4只是简单的在前面加2个字节0。

UCS- 4则主要用于保存辅助平面,例如Unicode 4.0中的第二辅助平面20000-20FFF - 21000-21FFF - 22000-22FFF - 23000-23FFF - 24000-24FFF - 25000-25FFF - 26000-26FFF - 27000-27FFF - 28000-28FFF - 29000-29FFF - 2A000-2AFFF - 2F000-2FFFF

总共增加了16个辅助平面,由原先的65536个编码扩展至将近100万编码。

统一了编码,如何兼容原先各国的文字编码呢?

这个时候需要codepage代码页。

codepage就是各国的文字编码和Unicode之间的映射表。比如简体中文和Unicode的映射表就是CP936。

代码页(Code Page)是个古老的专业术语,据说是IBM公司首先使用的。代码页和字符集的含义基本相同,代码页规定了适用于特定地区的字符集合,和这些字符的编码。也可以将代码页理解为字符和字节数据的映射表。

Windows为自己支持的代码页都编了一个号码。代码页的概念比较简单,就是一个字符编码方案。下是几个常用的codepage,相应的修改上面的地址的数字即可。

 

    * 874 (ANSI/OEM - 泰文)
    * 932 (ANSI/OEM - 日文 Shift-JIS)
    * 936 (ANSI/OEM - 简体中文 GBK)
    * 949 (ANSI/OEM - 韩文)
    * 950 (ANSI/OEM - 繁体中文 Big5)
    * 1250 (ANSI - 中欧)
    * 1251 (ANSI - 西里尔文)
    * 1252 (ANSI - 拉丁文 I)
    * 1253 (ANSI - 希腊文)
    * 1254 (ANSI - 土耳其文)
    * 1255 (ANSI - 希伯来文)
    * 1256 (ANSI - 阿拉伯文)
    * 1257 (ANSI - 波罗的海文)
    * 1258 (ANSI/OEM - 越南)
    * 437 (ANSI - 美国/加拿大英语)
    * 866 (ANSI - 俄文)
    * 65001(ANSI - unicode UFT-8)

最后一个65001,只是一个虚拟的映射表,实际只是一个算法而已。

从936中随意取一行,例如:0x9993 0x6ABD #CJK UNIFIED IDEOGRAPH

前面的编码是GBK的编码,后面的是Unicode。

通过查这张表,就能简单的实现GBK和Unicode之间的转换。

UTF-8是什么?

ASCII转换成UCS-2,只是在编码前插入一个0x0。用这些编码,会包括一些控制符,比如 或 /,这在UNIX和一些C函数中,将会产生严重错误。因此可以肯定,UCS-2不适合作为Unicode的外部编码。

因此,才诞生了UTF-8。那么UTF-8是如何编码的?又是如何解决UCS-2的问题呢?

例:
E4 BD A0 11100100 10111101 10100000
这是“你”字的UTF-8编码
4F 60 01001111 01100000
这是“你”的Unicode编码

按照UTF-8的编码规则,分解如下:xxxx0100 xx111101 xx100000
把除了x之外的数字拼接在一起,就变成“你”的Unicode编码。

注意UTF-8的最前面3个1,表示整个UTF-8串是由3个字节构成的。
经过UTF-8编码之后,再也不会出现敏感字符了,因为最高位始终为1。

以下是Unicode和UTF-8之间的转换关系表:
U-00000000 - U-0000007F: 0xxxxxxx
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

Unicode编码转换到UTF-8,简单的把Unicode字节流套到x中就变成UTF-8。

ISO 8859系列字符集

ISO 8859系列字符集是欧洲计算机制造商协会(ECMA)在上世纪80年代中期设计,并被国际标准化(ISO)组织采纳为国际标准。ISO 8859系列字符集目前有15个字符集,包括:

    * ISO 8859-1 大部分的西欧语系,例如英文、法文、西班牙文和德文等(Latin-1)
    * ISO 8859-2 大部分的中欧和东欧语系,例如捷克文、波兰文和匈牙利文等(Latin-2)
    * ISO 8859-3 欧洲东南部和其它各种文字(Latin-3)
    * ISO 8859-4 斯堪的那维亚和波罗的海语系(Latin-4)
    * ISO 8859-5 拉丁文与斯拉夫文(俄文、保加利亚文等)
    * ISO 8859-6 拉丁文与阿拉伯文
    * ISO 8859-7 拉丁文与希腊文
    * ISO 8859-8 拉丁文与希伯来文
    * ISO 8859-9 为土耳其文修正的Latin-1(Latin-5)
    * ISO 8859-10 拉普人、北欧与爱斯基摩人的文字(Latin-6)
    * ISO 8859-11 拉丁文与泰文
    * ISO 8859-13 波罗的海周边语系,例如拉脱维亚文等(Latin-7)
    * ISO 8859-14 凯尔特文,例如盖尔文、威尔士文等(Latin-8)
    * ISO 8859-15 改进的Latin-1,增加遗漏的法文、芬兰文字符和欧元符号(Latin-9)
    * ISO 8859-16 罗马尼亚文(Latin-10)

其中缺少的编号12据说是为了预留给天城体梵文字母(Deva-nagari)的。印地文和尼泊尔文都使用了这种在七世纪形成的字母表。由于印度定义了自己的编码ISCII(Indian Script Code for Information Interchange),所以这个编号就未被使用。ISO 8859系列字符集都是单字节字符集,即只使用0x00-0xFF对字符编码。

绝大多数字符集都与ASCII编码保持兼容,ISO 8859系列字符集也不例外,它们的0x00-0x7f都与ASCII码保持一致,各字符集的不同之处在于如何利用0x80-0xff的码位。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

最新评论及回复

最近发表


Powered By Z-Blog 1.8 Spirit Build 80605

Copyright www.chinapromoter.cn. Some Rights Reserved. 浙ICP备05022498号