您的位置:首页 > 其它

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。

最后附上源代码:

映射表文件并没有从0×00持续到0xFFFF,而是采取了精简策略。

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: