字符集编码的识别
阅读原文时间:2021年04月21日阅读:1

字符集编码的识别(一)

读取文本文件或者接收字节流时需要搞清字符编码才能正确处理,编码识别错误是出现乱码的主要原因。理解编码识别方法之前建议阅读:常用字符集编码的概要特性(一)常用字符集编码的概要特性(二)

通过约定识别

为了接收字节流时能正确识别编码,很多情况下发送字节流的同时会把字节流对应的编码发送给接收方,这种情况可以理解为发送和接收双方的约定。HTTP协议就有这样的约定,浏览器就是通过约定来识别网页的编码。HTTP协议的响应头会有这样的约定:

Content-Type: text/html;charset=utf-8

如果打开一个本地的Html文件,其中也会有关于字符编码的约定:

邮件客户端程序也是通过上述约定来识别字符的,在邮件的头部有Charset的声明。

UCS-2/UTF-16的BOM头也可以理解为是字符编码的约定,打开文本文件时可以用BOM来识别编码。

靠约定识别编码的情形很多,例如MySQL环境中有一组变量来约定客户端SQL语句的编码以及服务器返回内容的编码。可以用SQL命令来查看这组变量:

show variables like ‘%character_set%’;

如果没有约定就要尝试去猜测字符编码,以下会介绍几种猜测的方法。

通过编码规律识别

UTF-8编码是UCS-2/UCS-4编码按照一定规律转换得到的,UTF-8编码本身有也具有一定规律,这种规律可以作为识别字符编码的依据。下面给出识别一个字符串是否是UTF-8编码的PHP实现:

=0 && $str < 0×7f) { $i++; continue; } if($str< 0xc0 || $str>0xfd) return false;
$count = $str>0xfc?5:$str>0xf8?4:$str>0xf0?3:$str>0xe0?2:1;
if($i+$count > $str_len) return false;
$i++;
for($m=0;$m<$count;$m++) { if(ord($string[$i])<0×80 || ord($string[$i])>0xbf) return false;
$i++;
}
}
return true;
}
?>

用此规律识别UTF-8编码会有一定误差,其他编码也会有某些字符符合UTF-8编码规律的情况。例如GBK编码的“联通”、“学习”等词就符合UTF-8编码的规律。在Windows记事本中只写入“联通”两字后直接保存,重新打开时就会看见两个黑框。原因是记事本错误地把GBK编码的“联通”两字识别为UTF-8编码了,系统字体中没有这两个识别出来的字符,所以只能看见黑框。误把其他编码当作UTF-8编码的例子很多,例如访问URL:http://www.google.cn/search?q=%D1%A7%CF%B0,也会看到错误结果。“%D1%A7%CF%B0”是GBK编码的“学习”,Google把它当作了UTF-8编码。

供识别的字符串越长,出现这种识别错误的概率就越低。

通过编码范围识别

很多字符编码不像UTF-8编码存在明显规律,例如Big5、GBK、GB2312等。识别这些编码可以使用的方法是通过编码范围来识别。例如GB2312的编码范围是0xA1A1-0×7E7E,如果某个字符串中有字节不在此范围内,就可以认为该字符串不是GB2312编码。

通过编码范围识别的方法误差很大,原因是很多双字节编码的编码范围重合度很高,一个字符串同时落在几个编码的编码范围就很难确定。ISO-8859-1编码占用了0×00-0xff内所有空间,所以无法通过编码范围来识别。

基于语义的识别

基于语义识别字符编码的方法的本质是把文本流当作什么编码来理解更符合语义,具体可以根据字频、词频、上下文环境等方式识别。例如某段文本中“B5C4(’的’字的GBK编码)”两个字节出现的频度比较高,则该段文本是GBK编码的可能性就非常大。基于语义的识别准确度取决于供识别的文本流长度和所采用的识别语料。

字符集的识别

字符集编码的识别实际上有两部分,字符编码识别和字符集识别。多数情况下是识别编码,对于通用字符集(UCS)的编码(如UCS-2、UTF-8)有时需要识别字符集。例如在只希望处理中文内容的环境中,对拿到的UTF-8编码的文件就需要识别字符集,如果该文件中所有的字符都是韩文字符,就应该被抛弃。

可用的字符集识别方法很多:

  1. 通过编码转换来识别。如果把某段文本从UTF-8编码转换到GBK编码时有很多字符不能被转换,就可以认为该文件不是GBK字符集。通常编码转换程序会把不能转换的字符显示为’?'。
  2. 通过字符编码的范围来判断。CJK汉字在Unicode字符集中占有连续的位置,如果某个UTF-8文件中所有字符都在Unicode定义的CJK汉字区,可以认为该文件是UTF-8编码的中文文件。GBK编码包括俄文字符、日文字符等,这些字符在GBK编码中范围也是连续的。即使某个文件能从UTF-8编码正确转换到GBK编码,也有可能是UTF-8编码的俄文文件。这种情况也可以通过转换后编码的范围来判断。
  3. 基于语义的识别。

归类于: 字符集编码 — sawfish @ 11:46 pm 评论(0)

四月 21, 2007

常用字符集编码的概要特性(二)

BIG5

Big5是双字节编码,高字节编码范围是0×81-0xFE,低字节编码范围是0×40-0×7E和0xA1-0xFE。和GBK相比,少了低字节是0×80-0xA0的组合。0×8140-0xA0FE是保留区域,用于用户造字区。

Big5收录的汉字只包括繁体汉字,不包括简体汉字,一些生僻的汉字也没有收录。GBK收录的日文假名字符、俄文字符Big5也没有收录。因为Big5当中收录的字符有限,因此有很多在Big5基础上扩展的编码,如倚天中文系统。Windows系统上使用的代码页CP950也可以理解为是对Big5的扩展,在Big5的基础上增加了7个汉字和一些符号。Big5编码对应的字符集是GBK字符集的子集,也就是说Big5收录的字符是GBK收录字符的一部分,但相同字符的编码不同。

因为Big5也占用了ASCII的编码空间(低字节所使用的0×40-0×7E),所以Big5编码在一些环境下存在和GBK编码相同的问题,即低字节范围为0×40-0×7E的字符有可能会被误处理,尤其是低字节是0×5C(”/”)和0×7C(”|”)的字符。可以参考GBK一节相应说明。

尽管有些区别,大多数情况下可以把CP950当作Big5的别名。

ISO-8859-1

ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0×00-0xFF,0×00-0×7F之间完全和ASCII一致,0×80-0×9F之间是控制字符,0xA0-0xFF之间是文字符号。

ISO-8859-1收录的字符除ASCII收录的字符外,还包括西欧语言、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。欧元符号出现的比较晚,没有被收录在ISO-8859-1当中。

因为ISO-8859-1编码范围使用了单字节内的所有空间,在支持ISO-8859-1的系统中传输和存储其他任何编码的字节流都不会被抛弃。换言之,把其他任何编码的字节流当作ISO-8859-1编码看待都没有问题。这是个很重要的特性,MySQL数据库默认编码是Latin1就是利用了这个特性。ASCII编码是一个7位的容器,ISO-8859-1编码是一个8位的容器。

Latin1是ISO-8859-1的别名,有些环境下写作Latin-1。

UCS-2和UTF-16

Unicode组织和ISO组织都试图定义一个超大字符集,目的是要涵盖所有语言使用的字符以及其他学科使用的一些特殊符号,这个字符集就是通用字符集(UCS,Universal Character Set)。这两个组织经过协调,虽然在各自发展,但定义的字符位置是完全一致的。ISO相应的标准是ISO 10646。Unicode和ISO 10646都在不断的发展过程中,所以会有不同的版本号来标明不同的发展阶段,每个Unicode版本号都能找到相对应的ISO 10646版本号。

ISO 10646标准定义了一个31位的字符集。前两个字节的位置(0×0000-0xFFFD)被称为基本多语言面(Basic Multilingual Plane, BMP) ,超出两个字节的范围称作辅助语言面。BMP基本包括了所有语言中绝大多数字符,所以只要支持BMP就可以支持绝大多数场合下的应用。Unicode 3.0对应的字符集在BMP范围内。

UCS字符集为每个字符分配了一个位置,通常用“U”再加上某个字符在UCS中位置的16进制数作为这个字符的UCS表示,例如“U+0041”表示字符“A”。UCS字符U+0000到U+00FF与ISO-8859-1完全一致。

UCS-2、UTF-16是UCS字符集(或者说是Unicode字符集)实际应用中的具体编码方式。UCS-2是两个字节的等宽编码,因为只是使用了两个字节的编码空间,所以只能对BMP中的字符做编码。UTF-16是变长编码,用两个字节对BMP内的字符编码,用4个字节对超出BMP范围的辅助平面内的字符作编码。

UCS-2不同于GBK和Big5,它是真正的等宽编码,每个字符都使用两个字节,这个特性在字符串截断和字符数计算时非常方便。

UTF-16是UCS-2的超集,UTF-16编码的两字节编码方式完全和UCS-2相同,也就是说在BMP的框架内UCS-2完全等同与UTF-16。实际情况当中常常把UCS-16当作UCS-2的别名。

UCS-2和UTF-16在存储和传输时会使用两种不同的字节序,分别是big endian和little endian(大尾和小尾)。例如“啊”(U+554A)用big endian表示就是0×554A,用little endian表示就是0×4A55。UCS-2和UTF-16默认的字节序是big endian方式。在传输过程中为了说明字节序需要在字节流前加上BOM(Byte order Mark),0xFEFF表示是big endian,0xFFFE表示是little endian。UCS-2BE、UCS-2LE是实际应用中使用的编码名称,对应着big endian和little endian,UTF-16BE、UTF-16LE也是如此。因为默认是BE字节序,所以可以把UCS-2当做是UCS-2BE的别名。

在UCS编码中有一个叫做“ZERO WIDTH NO-BREAK SPACE”的字符,它的编码是U+FEFF,是个没有实际意义的字符。UCS规范建议我们在传输字节流前,先传输字符“ZERO WIDTH NO-BREAK SPACE”,如果传输的ZERO WIDTH NO-BREAK SPACE是0xFEFF就说明是big endian,反之就是little endian。

UCS-2和UTF-16也可以理解为和ASCII以及ISO-8859-1兼容,在ASCII编码或者ISO-8859-1编码的每个字节前加上0×00,就得到相应字符的UCS-2编码。

UCS-2和UTF-16中会使用0×00作为某个字符编码的一部分,某些系统会把0×00当作字符串结束的标志,在处理UCS-2或UTF-16编码时会出现问题。

UTF-8

UTF-8是UCS字符集的另一种编码方式,UTF-16的每个单元是两个字节(16位),而UTF-8的每个单元是一个字节(8位)。UTF-16中用一个或两个双字节表示一个字符,UTF-8中用一个或几个单字节表示一个字符。

可以认为UTF-8编码是根据一定规律从UCS-2转换得到的,从UCS-2到UTF-8之间有以下转换关系:

UCS-2

UTF-8

U+0000 - U+007F

0_xxxxxxx_

U+0080 - U+07FF

110_xxxxx_ 10_xxxxxx_

U+0800 - U+FFFF

1110_xxxx_ 10_xxxxxx_ 10_xxxxxx_

例如“啊”字的UCS-2编码是0×554A,对应的二进制是0101 0101 0100 1010,转成UTF-8编码之后的二进制是1110 0101 10 010101 10 001010,对应的十六进制是0xE5958A。

UCS-4也是一种UCS字符集的编码方式,是使用4个字节的等宽编码,可以用UCS-4来表示BMP之外的辅助面字符。UCS-2中每两个字节前再加上0×0000就得到了BMP字符的UCS-4编码。从UCS-4到UTF-8也存在转换关系,根据这种转换关系,UTF-8最多可以使用六个字节来编码UCS-4。

根据UTF-8的生成规律和UCS字符集的特性,可以看到UTF-8具有的特性:

  1. UTF-8完全和ASCII兼容,也就是说ASCII对应的字符在UTF-8中和ASCII编码完全一致。范围在0×00-0×7F之内的字符一定是ASCII字符,不可能是其他字符的一部分。GBK和Big5都存在的缺陷在UTF-8中是不存在的。
  2. 大于U+007F的UCS字符,在UTF-8编码中至少是两个字节。
  3. UTF-8中的每个字符编码的首字节总在0×00-0xFD之间(不考虑UCS-4支持的情况,首字节在0×00-0xEF之间)。根据首字节就可以判断之后连续几个字节。
  4. 非首字节的其他字节都在0×80-0xBF之间;0xFE和0xFF在UTF-8中没有被用到。
  5. GBK编码中的汉字字符都在UCS-2中的范围都在U+0800 - U+FFFF之间,所以每个GBK编码中的汉字字符的UTF-8编码都是3个字节。但GBK中包含的其他字符的UTF-8编码就不一定是3个字节了,如GBK中的俄文字符。

在UTF-8的编码的传输过程中即使丢掉一个字节,根据编码规律也很容易定位丢掉的位置,不会影响到其他字符。在其他双字节编码中,一旦损失一个字节,就会影响到此字节之后的所有字符。从这点可以看出UTF-8编码非常适合作为传输编码。

归类于: 字符集编码 — sawfish @ 10:52 pm 评论(0)

四月 18, 2007

常用字符集编码的概要特性(一)

搞清常用编码特性是解决字符集编码问题的基础。字符集编码的识别与转换、分析各种乱码产生的原因、编程操作各种编码字符串(例如字符数计算、截断处理)等都需要弄清楚编码的特性。

了解一种字符集编码主要是要了解该编码的编码范围,编码对应的字符集(都包含哪些字符),和其他字符集编码之间的关系等。

ASCII

ASCII码是7位编码,编码范围是0×00-0×7F。ASCII字符集包括英文字母、阿拉伯数字和标点符号等字符。其中0×00-0×20和0×7F共33个控制字符。

只支持ASCII码的系统会忽略每个字节的最高位,只认为低7位是有效位。HZ字符编码就是早期为了在只支持7位ASCII系统中传输中文而设计的编码。早期很多邮件系统也只支持ASCII编码,为了传输中文邮件必须使用BASE64或者其他编码方式。

GB2312

GB2312是基于区位码设计的,区位码把编码表分为94个区,每个区对应94个位,每个字符的区号和位号组合起来就是该汉字的区位码。区位码一般 用10进制数来表示,如1601就表示16区1位,对应的字符是“啊”。在区位码的区号和位号上分别加上0xA0就得到了GB2312编码。

区位码中01-09区是符号、数字区,16-87区是汉字区,10-15和88-94是未定义的空白区。它将收录的汉字分成两级:第一级是常用汉字 计3755个,置于16-55区,按汉语拼音字母/笔形顺序排列;第二级汉字是次常用汉字计3008个,置于56-87区,按部首/笔画顺序排列。一级汉 字是按照拼音排序的,这个就可以得到某个拼音在一级汉字区位中的范围,很多根据汉字可以得到拼音的程序就是根据这个原理编写的。

GB2312字符集中除常用简体汉字字符外还包括希腊字母、日文平假名及片假名字母、俄语西里尔字母等字符,未收录繁体中文汉字和一些生僻字。可以用繁体汉字测试某些系统是不是只支持GB2312编码。

GB2312的编码范围是0xA1A1-0×7E7E,去掉未定义的区域之后可以理解为实际编码范围是0xA1A1-0xF7FE。

EUC-CN可以理解为GB2312的别名,和GB2312完全相同。

区位码更应该认为是字符集的定义,定义了所收录的字符和字符位置,而GB2312及EUC-CN是实际计算机环境中支持这 种字符集的编码。HZ和ISO-2022-CN是对应区位码字符集的另外两种编码,都是用7位编码空间来支持汉字。区位码和GB2312编码的关系有点像 Unicode和UTF-8。

GBK

GBK编码是GB2312编码的超集,向下完全兼容GB2312,同时GBK收录了Unicode基本多文种平面中的所有CJK汉字。同 GB2312一样,GBK也支持希腊字母、日文假名字母、俄语字母等字符,但不支持韩语中的表音字符(非汉字字符)。GBK还收录了GB2312不包含的 汉字部首符号、竖排标点符号等字符。

GBK的整体编码范围是为0×8140-0xFEFE,不包括低字节是0×7F的组合。高字节范围是0×81-0xFE,低字节范围是0×40-7E和0×80-0xFE。

低字节是0×40-0×7E的GBK字符有一定特殊性,因为这些字符占用了ASCII码的位置,这样会给一些系统带来麻烦。

有些系统中用0×40-0×7E中的字符(如“|”)做特殊符号,在定位这些符号时又没有判断这些符号是不是属于某个 GBK字符的低字节,这样就会造成错误判断。在支持GB2312的环境下就不存在这个问题。需要注意的是支持GBK的环境中小于0×80的某个字节未必就 是ASCII符号;另外就是最好选用小于0×40的ASCII符号做一些特殊符号,这样就可以快速定位,且不用担心是某个汉字的另一半。Big5编码中也存在相应问题。

CP936和GBK的有些许差别,绝大多数情况下可以把CP936当作GBK的别名。

GB18030

GB18030编码向下兼容GBK和GB2312,兼容的含义是不仅字符兼容,而且相同字符的编码也相同。GB18030收录了所有Unicode3.1中的字符,包括中国少数民族字符,GBK不支持的韩文字符等等,也可以说是世界大多民族的文字符号都被收录在内。

GBK和GB2312都是双字节等宽编码,如果算上和ASCII兼容所支持的单字节,也可以理解为是单字节和双字节混合的变长编码。GB18030编码是变长编码,有单字节、双字节和四字节三种方式。

GB18030的单字节编码范围是0×00-0×7F,完全等同与ASCII;双字节编码的范围和GBK相同,高字节是0×81-0xFE,低字节 的编码范围是0×40-0×7E和0×80-FE;四字节编码中第一、三字节的编码范围是0×81-0xFE,二、四字节是0×30-0×39。

Windows中CP936代码页使用0×80来表示欧元符号,而在GB18030编码中没有使用0×80编码位,用其他位置来表示欧元符号。这可以理解为是GB18030向下兼容性上的一点小问题;也可以理解为0×80是CP936对GBK的扩展,而GB18030只是和GBK兼容良好。

归类于: 字符集编码 — sawfish @ 11:41 pm 评论(0)

四月 7, 2007

Vim对中文编码的支持

1、支持中文编码的基础

Vim要更好地支持中文编码需要两个特性:+multi_byte和+iconv,可以用|:version|命令检查当前使用的Vim是否支持,否则的话需要重新编译。

2、影响中文编码的设置项

Vim中有几个选项会影响对多字节编码的支持:

  • encoding(enc):encoding是Vim的内部使用编码,encoding的设置会影响Vim内部的Buffer、消息文字等。在Unix环境下,encoding的默认设置等于locale;Windows环境下会和当前代码页相同。在中文Windows环境下encoding的默认设置是cp936(GBK)。
  • fileencodings(fenc):Vim在打开文件时会根据fileencodings选项来识别文件编码,fileencodings可以同时设置多个编码,Vim会根据设置的顺序来猜测所打开文件的编码。
  • fileencoding(fencs) :Vim在保存新建文件时会根据fileencoding的设置编码来保存。如果是打开已有文件,Vim会根据打开文件时所识别的编码来保存,除非在保存时重新设置fileencoding。
  • termencodings(tenc):在终端环境下使用Vim时,通过termencoding项来告诉Vim终端所使用的编码。

3、Vim中的编码转换

Vim内部使用iconv库进行编码转换,如果这几个选项所设置的编码不一致,Vim就有可能会转换编码。打开已有文件时会从文件编码转换到encoding所设置的编码;保存文件时会从encoding设置的编码转换到fileencoding对应的编码。经常会看到Vim提示[已转换],这是表明Vim内部作了编码转换。终端环境下使用Vim,会从termencoding设置的编码转换到encoding设置的编码。

可以用|:help encoding-values|列出Vim支持的所有编码。

4、具体应用环境的设置

  • 只编辑GBK编码的文件

set fileencodings=cp936
set fileencoding=cp936
set encoding=cp936

  • 只编辑UTF-8编码的中文文件

set fileencodings=utf-8
set fileencoding=utf-8
set encoding=cp936 或者 set encoding=utf-8

  • 同时支持GBK和UTF-8编码

set fileencodings=ucs-bom,utf-8,cp936
set fileencoding=utf-8
set encoding=cp936 或者 set encoding=utf-8

  • 如果在终端环境下使用Vim,需要设置termencoding和终端所使用的编码一致。例如:

set termencoding=cp936 或者 set termencoding=utf-8

Windows记事本编辑UTF-8编码文件时会在文件头上加上三个字节的BOM:EFBBBF。如果fileencodings中设置ucs-bom的目的就是为了能够兼容用记事本编辑的文件,不需要的话可以去掉。Vim在保存UTF-8编码的文件时会去掉BOM。去掉BOM的最大好处是在Unix下能够使用cat a b>c来正确合并文件,这点经常被忽略。

5、FAQ

  1. 为什么在Vim中一次只能删除半个汉字?

    因为encoding设置错误,把encoding设置为cp936就可以解决此问题。在Unix环境下Vim会根据locale来设置默认的encoding,如果没有正确设置locale并且没有设置encoding就会一次只能删除半个汉字。

  2. VIM为什么不能输入繁体字?

    把euc-cn或者GB2312改为cp936就可以了。euc-cn是GB2312的别名,不支持繁体汉字。cp936是GBK的别名,是GB2312的超集,可以支持繁体汉字。

  3. VIM为什么提示不能转换?

    因为在编译Vim时没有加入iconv选项,重新编译Vim才能解决。

  4. 如何打开一个GBK编码的文件并另存为UTf-8编码?

    保存文件时运行命令|:set fileencoding=utf-8|就可以了。
     

归类于: 字符集编码 — sawfish @ 11:43 pm 评论(0)

四月 1, 2007

浏览器发送URL的编码特性

尽管有很多规范URL的标准,例如RFC 3987,但实际应用中却非常混乱。本文主要介绍浏览器发送URL到服务器的一些特性,作为开发和应用的参考。

通常浏览器会用两种编码方式发送URL到服务器,分别是UTF-8和ANSI(当前系统语言设置,在Windows系统中可以理解为当前代码页)。接下来分别介绍几种常用浏览器发送URL的编码特性。

一、直接在地址栏输入URL的情况

中文Windows环境下,假如直接在浏览器的地址栏输入URL:

http://www.charset.cn/中国.html?kw=中国

  1. IE浏览器特性

     

    PATH部分

    参数部分

    UTF-8模式(默认)

    %E4%B8%AD%E5%9B%BD.html

    kw=中国

     

    UTF-8编码、urlencode

    GBK编码、无urlencode

    ANSI模式

    中国.html

    kw=中国

     

    GBK编码、无urlencode

    GBK编码、无urlencode

    中文Windows环境下,IE中默认发送的URL的PATH部分是UTF-8编码,参数部分是GBK编码。IE的设置选项中有一项是“总是以 UTF-8 发送URL”可以改变发送URL的编码为ANSI。

  2. FireFox浏览器特性

     

    PATH部分

    参数部分

    UTF-8模式

    %E4%B8%AD%E5%9B%BD.html

    kw=%E4%B8%AD%E5%9B%BD

     

    UTF-8编码、urlencode

    UTF-8编码、urlencode

    ANSI模式(默认)

    %D6%D0%B9%FA.html

    kw=%D6%D0%B9%FA

     

    GBK编码、urlencode

    GBK编码、urlencode

    中文Windows环境下FireFox中默认发送的URL的PATH和参数都是GBK编码,在FireFox地址栏输入“about:config”,找到选项“network.standard-url.encode-utf8”,即可改变发送URL的编码方式。

  3. Opera浏览器特性

     

    PATH部分

    参数部分

    UTF-8模式(默认)

    %E4%B8%AD%E5%9B%BD.html

    kw=%E4%B8%AD%E5%9B%BD

     

    UTF-8编码、urlencode

    UTF-8编码、urlencode

二、来自网页中的链接

在不同的浏览器中打开不同编码的网页中的链接,特性也不相同。在不改变浏览器默认选项情况下访问不同编码的网页中以下链接:

http://www.charset.cn/中国.html?kw=中国

  1. IE浏览器特性

     

    PATH部分

    参数部分

    UTF-8网页

    %E4%B8%AD%E5%9B%BD.html

    kw=中国

     

    UTF-8编码、urlencode

    UTF-8编码、无urlencode

    GBK网页

    %E4%B8%AD%E5%9B%BD.html

    kw=中国

     

    UTF-8编码、urlencode

    GBK编码、无urlencode

  2. FireFox浏览器特性

     

    PATH部分

    参数部分

    UTF-8网页

    %E4%B8%AD%E5%9B%BD.html

    kw=%E4%B8%AD%E5%9B%BD

     

    UTF-8编码、urlencode

    UTF-8编码、urlencode

    GBK网页

    %D6%D0%B9%FA.html

    kw=%D6%D0%B9%FA

     

    GBK编码、urlencode

    GBK编码、urlencode

如果改变IE默认选项为ANSI模式或者将FireFox改为UTF-8模式的访问结果可以自己测试。

几点说明:

  1. 对于开发人员而言,一定要考虑到不同环境下URL编码的不同,才能实现系统更好的兼容性。兼容性好的系统必须要能够识别来自客户端URL的编码,才能正确处理。
    例如在Opera浏览器地址栏直接输入“http://www.baidu.com/s?wd=我们”,就会发现不能正确访问。
  2. 不同的WEB服务器对各种编码的URL处理也不相同,尽量不要使用中文字符作文件名。
  3. 如果写入网页中的链接包括中文字符,最好使用urlencode处理,才能和当前网页编码无关。否则有可能不能正确访问。
  4. 很多情况下浏览器的地址栏看到URL并不等同于发送到服务器的URL。要正确查看浏览器发送的到服务器URL,最好借助一些工具分析HTTP的请求头。

归类于: 字符集编码 — sawfish @ 5:40 pm 评论(1)

三月 31, 2007

什么是字符集?什么是编码?

字符(Charcter)是文字与符号的总称,包括文字、图形符号、数学符号等。

一组抽象字符的集合就是字符集(Charset)。字符集常常和一种具体的语言文字对应起来,该文字中的所有字符或者大部分常用字符就构成了该文字的字符集,比如英文字符集。一组有共同特征的字符也可以组成字符集,比如繁体汉字字符集、日文汉字字符集。字符集的子集也是字符集。

计算机要处理各种字符,就需要将字符和二进制内码对应起来,这种对应关系就是字符编码(Encoding)。制定编码首先要确定字符集,并将字符集内的字符排序,然后和二进制数字对应起来。根据字符集内字符的多少,会确定用几个字节来编码。每种编码都限定了一个明确的字符集合,叫做被编码过的字符集(Coded Character Set),这是字符集的另外一个含义。通常所说的字符集大多是这个含义。

因为制定编码的同时往往也制定了字符集,所以经常把字符集和编码混为一谈,具体区分细节不用细