GBK、Shift-JIS、BIG5编码检测算法
2012-08-30 16:33
701 查看
GBK、Shift-JIS、BIG5编码检测算法
字符串的编码检测需要使用自定义的映射表,使用系统自带的Codepage是不大可能有准确率的,系统Codepage会将它所有没定义的字符映射为空格。GBK、Shift-JIS、BIG5的码表空间都是不连贯的,而它们的有效空间也不完全重合,这为检测编码类型提供了可能性。
检测算法:
1、建立字符映射表:将任一ANSI编码的所有字符做全映射,从0×00到0xFFFF都有Unicode字符对应,但需要注意的是没有定义的字符统统映射到Unicode的0xFFFD(共三个映射表,既可用于检测也可用于转换)。
2、预设字符串的编码是Shift-JIS。
3、使用Shift-JIS的映射表从字符串第一个字符开始检测直至最后一个字符。如果遇到有字符映射到0xFFFD,设置预设编码是GBK,立刻停止步骤3,跳至步骤4。
4、如果预设编码是GBK,使用GBK的映射表从字符串第一个字符开始检测直至最后一个字符。如果遇到有字符映射到0xFFFD,设置预设编码是BIG5,立刻停止步 骤4,跳至步骤5。
5、如果预设编码是BIG5,使用BIG5的映射表从字符串第一个字符开始检测直至最后一个字符。如果遇到有字符映射到0xFFFD,设置预设编码是未知编码,立刻停止步 骤5,跳至步骤6。
6、返回预设编码。
这个算法的编码检测优先度是Shift-JIS>GBK>BIG5,也即如果顺利通过当前检测,则跳过后面所有检测。事实上,有大量字符串是能通过所有检测的。例如只有一个字符的字符串,假设这个字符是0×8140,在三个编码当中,都不会映射到Unicode的0xFFFD,因此能通过所有检测。但这没意义了。设定了优先度后是为了告诉用户最可能的一种编码。
为什么设定Shift-JIS>GBK>BIG5?
Shift-JIS的码表空间是0×00-0x7F、0xA1-0xDF、0×8140-0xFC4B
GBK的码表空间是0×00-0x7F、0×8140-0xFEFE
BIG5的码表空间是0×00-0x7F、0×8140-0xFEFE
但双字节段(0×8140以上)都不是全部已定义,Shift-JIS在0×8140以上的有效字符数是7724,GBK是21885,BIG5是19782。
GBK的覆盖面最大,有效空间基本覆盖了Shift-JIS,因此一个字符串如果能通过Shift-JIS检测,也差不多能通过GBK检测。如果将GBK的优先度设得比Shift-JIS高,那么大量真正是Shift-JIS编码的字符串就压根没机会返回给用户了。从反方向看,GBK中存在数量庞大的字符Shift-JIS没定义,Shift-JIS是高度覆盖不住GBK的,一个GBK文本从概率上没那么容易检测成Shift-JIS。也即:如果一个文本的真正编码是Shift-JIS,那么优先使用Shift-JIS检测自然不会有问题;如果它是GBK,那么优先使用Shift-JIS检测也不大会返回Shift-JIS。因此Shift-JIS应当优先于GBK。
Shift-JIS和BIG5的关系的考虑也类似。
从转换日系音乐cue、日文小说的宅用途出发,也应当将Shift-JIS设置为最高。
下面三张图是是Shift-JIS编码的小说“文学少女”と死にたがりの道化的转换结果。左边是当作本地编码的处理结果,可以无视。右边才是转换结果。
(程序和文本下载:http://code.google.com/p/unicue/downloads/detail?name=Ansi2Unicode_1.01.zip)
使用Shift-JIS映射表转换,结果自然是正确的。
强行使用GBK映射表转换,没有出现标记0xFFFD(0xFFFD:�),也即能通过GBK检测
强行使用Big5转换,出现0xFFFD标记,也即通不过BIG5检测。BIG5跟Shift-JIS的有效空间重合度没那么高,区分相对容易一点
另外一个GBK文本强行使用Shift-JIS转换的结果。很容易就出现了0xFFFD标记
那么GBK和BIG5的优先度应该谁高呢?这里就见仁见智了。GBK的字符数比BIG5多,从概率上GBK相对容易覆盖住BIG5,BIG5相对不容易覆盖住GBK。倘若采用Shift-JIS和GBK之间的比较方法,应该是BIG5的优先度比GBK高。但从实际情况来看,真正BIG5编码的文本强行使用GBK映射表转换比较容易出现0xFFFD标记,真正GBK编码的文本强行使用BIG5映射表转换反而不容易出现0xFFFD标记。
GBK文本强行使用BIG5映射表转换的结果,不容易出现0xFFFD标记
BIG5文本使用BIG5映射表转换,正常的结果
BIG5文本强行使用GBK映射表转换,很容易出现0xFFFD标记
现实结果和表面现象完全相反。如果一个文本的真正编码是GBK,那么优先使用GBK检测自然不会有问题;如果它是BIG5,那么优先使用GBK检测也不大会返回GBK。因此余倾向于GBK的优先度高于BIG5。
最后附上源代码:
GBK和BIG5的映射表范围均是0×8140-0xFFFF(其中未定义的字符都映射到0xFFFD),转换是对0×80-0x813F的字符也都映射到0xFFFD,检测则是立刻退出。Shift-JIS的映射表由两段凑在一起,因此有两个偏移,范围是0xA1-0xDF和0×8140-0xFFFF,转换是对0×80-0xA0和0xE0-0x813F的字符也都映射到0xFFFD,检测是立刻退出。最后的还有一个检测会对0×8140-0xFFFF的字符把关。代码实现和算法略有出入,但基本一致。
http://kuyur.info/blog/archives/635
相关文章推荐
- 常用编码:Shift_JIS, GBK,EUCKR,Big5,UTF8,CP1252
- ASCII,unicode, utf8 ,big5 ,gb2312,gbk,gb18030等几种常用编码区别
- C# utf-8编码时转换成shift-jis时出现乱码问题的处理
- 字符编码 Unicode UTF-8,GB2312,shift-jis编码判断。
- UTF-8、GB2312、GB18030、GBK和BIG5等字符集编码范围的具体说明
- 字符编码 Unicode UTF-8,GB2312,shift-jis编码判断。
- 字符编码 Unicode UTF-8,GB2312,shift-jis编码判断。
- AS3中UTF-8转GB2312、BIG5、GBK编码的类包
- GBK,BIG5等字符集编码局限的具体申明
- 将utf8等编码格式转换为shift_jis格式
- 中文的几个编码 GB2312、GBK、GB18030、GB13000、BIG5
- 记事本怎么显示Shift-JIS编码的日文啊
- 详解ASCII GB2312(BIG5) GBK GB18030 Unicode UTF-8 编码历史与定义
- 字符集编码(GBK,BIG5,UNICODE等)与C++的string/wstring .
- GBK,BIG5等字符集编码范围的具体说明 (转)
- 工具方法,将字符创由一种编码转换成另一种编码,UTF-8,GBK,ISO,BIG5。。。。。。
- C# utf-8编码时转换成shift-jis时出现乱码问题的处理
- 将utf8等编码格式转换为shift_jis格式
- 字符编码:ANSI,ASCII,GB2312,GBK,Big5,Unicode和UTF-8
- UTF-8、GB2312、GB18030、GBK和BIG5等字符集编码范围的具体说明