最近由于项目需要,对简体中文转拼音的算法作了一些了解,然而在google找到的大多是获得简体中文拼音首字母的算法,好不容易让我找到了一个sunrise.spell的类,专门用于中文转完整拼音,觉得的确做得不错,于是对它的算法作了一些分析,总的来说觉得还是比较简单的,拿出来与大家分享。
我们先来学习一些准备知识。GB2312编码对于我们中国人是再熟悉不过了,我先简单的分析一下它的编码规则。GB2312编码包括符号、数字、字母、日文、制表符等,当然最主要的部分还是中文,它采用16位编码方式,简体中文的编码范围从B0A1一直到F7FE,完整编码表可以参考http://ash.jp/code/cn/gb2312tbl.htm。如果我们把该编码的每8位用十进制来表示就是[176 | 161]到[247 | 254],这样对于每个中文字符,我们都可以通过两个值来表示它,如“啊”就是[176 | 161],“我”则是[206 | 210]。
通过上面的方法,我们就可以通过一个二维坐标对每一个中文字进行定位,从而建立一个二维表来实现中文和拼音的对应关系。当然我们会忽略一些特殊情况,比如汉字的多音字问题。由于一个拼音可能对应多个汉字,而拼音的组合本来就不多,因此我们首先建立一个拼音音节表,代码如下,里面列出了所有可能的组合情况,该表是一维数组。
在上面提到的二维表中,我们会保存音节表的索引值,来对应一个音节组合,如bao,而不是直接把音节组合保存在二维数组中,这样可以有效减少内存消耗。因此,二位数组中的所有值都应该是索引值,如数组元素[176][161]对应的应该是a的索引值0。值得注意的是由于GB2312对应的字符量比较大,而且半角字符不需要做转换,sunrise的类把其中的半角部分全部省略掉了,因此它的实际值是从[129 | 64]开始的,即8140开始的。
至此,我已经把原理解释了一遍,可能不是很容易理解,下面我们来举个例子说明一下程序流程。
首先输入汉字“我”,首先程序初始化一个GB2312编码对象
System.Text.Encoding encoding = System.Text.Encoding.GetEncoding("GB2312");
然后通过该对象获得“我”的编码数组
byte[] local = encoding.GetBytes(“我”);
local中的值应该是local[0]=206; local[1]=210
假设我们的二维数组叫_spellCodeIndex那么我们就通过_spellCodeIndex[local[0]-129,local[1]-64]获得“我”对应的拼音音节索引值,即327
再查音节组合表,得索引327对应的是"wo",这样就完成了中文到拼音的转换
完整c#类可以在这里下载。
本人看了C#源代码设计思路如下:
首先:创建一个枚举类中设置拼音的三种转换方式:(1 。只转换拼音首字母,默认转换全部 2转换位置汉字为问号,默认不转换,3保留非字母,非数字字符,默认不保留)
然后创建汉语拼音转换类:
创建一个拼音代码表数组:一个拼音索引表为二维数组:一个罗马字符数组,一个希腊字符数组,一个转换的方法:
转换的思路如下首先将汉语字符串转换为GB2312形式的字节数组,然后循环判断是否为GBK字符集字符,如果时则判断是否为全角ASCII码字符或罗马数字或者希腊字符,默认为汉字转换的byte数组,将第一个数组减129,将二个减64得到拼音索引数减1即得到拼音索引字符的索引。循环执行到最后将得到所有的拼音信息。