最近在倒腾与搜索相关的拼音检查技术,顺便看了一下中文转拼音开源插件pinyin4j的源码,参考资料:http://blog.csdn.net/hfhwfw/archive/2010/11/23/6030816.aspx整理了一下笔记:
pinyin4j是一个支持将简体和繁体中文转换到成拼音的Java开源类库,作者是Li Min ([email protected])。
1. pinyin4j的官方下载地址:http://sourceforge.net/projects/pinyin4j/files/,目前最新的版本是2.5.0
2. 下载解压后的目录结构及说明如下
- doc : pinyin4j的api文档
- lib : pinyin4j的jar包
- src : pinyin4j的源代码
- CHANGELOG.txt : pinyin4j的版本更新日志
- COPYING.txt : LICENSE说明
- README.txt : pinyin4j的概要介绍
3. 源码解析
net/sourceforge/pinyin4j
ChineseToPinyinResource:读取/pinyindb/unicode_to_hanyu_pinyin.txt
GwoyeuRomatzyhResource:读取/pinyindb/pinyin_gwoeu_mapping.xml
GwoyeuRomatzyhTranslator:汉语拼音转换为Gwoyeu拼音
PinyinRomanizationResource:读取/pinyindb/pinyin_mapping.xml
PinyinRomanizationType:定义汉语拼音的六种类型(pinyin4j支持将汉字转化成六种拼音表示法。其对应关系是:汉语拼音-Hanyu Pinyin,通用拼音-Tongyong Pinyin, 威妥玛拼音(威玛拼法)-Wade-Giles Pinyin, 注音符号第二式-MPSII Pinyin, 耶鲁拼法-Yale Pinyin和国语罗马字-Gwoyeu Romatzyh)
PinyinRomanizationTranslator:拼音转换,convertRomanizationSystem(源拼音字符串,源拼音类型,目标拼音类型)
PinyinFormatter:汉语拼音格式化(如:根据提供的格式格式化拼音字符串;注音标等方法)
PinyinHelper:音标格式化方法类(六种拼音类型的获取方法等)
ResourceHelper:从classpath路径下读取文件流BufferedInputStream
TextHelper:获取汉语拼音中拼音或音调数字
extractToneNumber返回音调数字,如输入:luan4 返回:4
extractPinyinString返回汉语拼音前的拼音,如输入:luan4 返回:luan
/format
HanyuPinyinCaseType:定义汉语拼音大小写类型(控制生成的拼音是以大写方式显示还是以小写方式显示)
- LOWERCASE :guó
- UPPERCASE :GUÓ
HanyuPinyinToneType:定义汉语拼音声调类型
- WITH_TONE_NUMBER(以数字代替声调) : zhong1 zhong4
- WITHOUT_TONE (无声调) : zhong zhong
- WITH_TONE_MARK (有声调) : zhōng zhòng
HanyuPinyinVCharType:定义汉语拼音字符u的类型(碰到unicode 的ü 、v 和 u时的显示方式)
- WITH_U_AND_COLON : lu:3
- WITH_V : lv3
- WITH_U_UNICODE : lü3
HanyuPinyinOutputFormat:拼音格式类型构造类
/exception 异常类
BadHanyuPinyinOutputFormatCombination:拼音格式化组合错误异常,如一下组合:
LOWERCASE-WITH_V-WITH_TONE_MARK LOWERCASE-WITH_U_UNICODE-WITH_TONE_MARK
UPPERCASE-WITH_V-WITH_TONE_MARK UPPERCASE-WITH_U_UNICODE-WITH_TONE_MARK
其主要思路:
1)先通过汉字字符的unicode编码从unicode_to_hanyu_pinyin.txt找到对应的带声调数字的拼音
2)根据给定的输出格式化要求对该带声调的数字拼音进行格式化处理
3)在各个拼音之间可以相互转换:
根据pinyin_mapping.xml可以找到汉语拼音对应其他四种格式,如:
<item>
<Hanyu>a</Hanyu>
<Wade>a</Wade>
<MPSII>a</MPSII>
<Yale>a</Yale>
<Tongyong>a</Tongyong>
</item>
根据pinin_gwoyeu_mapping.xml可以找出汉语拼音与Gwoyeu不同声调对应的格式,如:
<item>
<Hanyu>a</Hanyu>
<Gwoyeu_I>a</Gwoyeu_I>
<Gwoyeu_II>ar</Gwoyeu_II>
<Gwoyeu_III>aa</Gwoyeu_III>
<Gwoyeu_IV>ah</Gwoyeu_IV>
<Gwoyeu_V>.a</Gwoyeu_V>
</item>
4. 字符串转化成拼音Java代码示例
代码:
import java.util.HashSet; import java.util.Set; import net.sourceforge.pinyin4j.PinyinHelper; import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType; import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; public class Pinyin4j { public static Set<String> getPinyin(String src){ if(src != null && !src.trim().equalsIgnoreCase("")){ char[] srcChar; srcChar = src.toCharArray(); //汉语拼音格式输出类 HanyuPinyinOutputFormat hanYuPinOutputFormat = new HanyuPinyinOutputFormat(); //输出设置,大小写,音标方式等 hanYuPinOutputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); //小写 hanYuPinOutputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); //无音调 hanYuPinOutputFormat.setVCharType(HanyuPinyinVCharType.WITH_V); //‘¨¹‘ is "v" String[][] temp = new String[src.length()][]; for(int i=0;i<srcChar.length;i++){ char c = srcChar[i]; //是中文或者a-z或者A-Z转换拼音(我的需求,是保留中文或者a-z或者A-Z) if(String.valueOf(c).matches("[//u4E00-//u9FA5]+")){ //中文字符 try{ temp[i] = PinyinHelper.toHanyuPinyinStringArray(srcChar[i],hanYuPinOutputFormat); }catch(BadHanyuPinyinOutputFormatCombination e){ e.printStackTrace(); } }else if(((int)c>=65&&(int)c<=90)||((int)c>=97&&(int)c<=122)){ //英文字母 temp[i] = new String[]{String.valueOf(srcChar[i])}; }else{ //其他字符 temp[i] = new String[]{""}; } } String[] pinyinArray = ExChange(temp); Set<String> pinyinSet = new HashSet<String>(); for(int i=0;i<pinyinArray.length;i++){ pinyinSet.add(pinyinArray[i]); } return pinyinSet; } return null; } /** * 字符串集合转换字符串(逗号分隔) * @param stringSet * @return */ public static String makeStringByStringSet(Set<String> stringSet,String separator){ StringBuilder str = new StringBuilder(); int i=0; for(String s :stringSet){ if(i == stringSet.size() - 1){ str.append(s); }else{ str.append(s+separator); } i++; } return str.toString().toLowerCase(); } private static String[] ExChange(String[][] strJaggedArray) { String[][] temp = DoExchange(strJaggedArray); return temp[0]; } private static String[][] DoExchange(String[][] strJaggedArray) { int len = strJaggedArray.length; if(len >= 2){ int len1 = strJaggedArray[0].length; int len2 = strJaggedArray[1].length; int newlen = len1*len2; String[] temp = new String[newlen]; int index = 0; for(int i=0;i<len1;i++){ for(int j=0;j<len2;j++){ temp[index] = strJaggedArray[0][i]+strJaggedArray[1][j]; index++; } } String[][] newArray = new String[len-1][]; for(int i=2;i<len;i++){ newArray[i-1] = strJaggedArray[i]; } newArray[0] = temp; return DoExchange(newArray); }else{ return strJaggedArray; } } /** * 只转换汉字为拼音,其他字符不变 * @param src * @return */ public static String getPinyinWithMark(String src){ if(src != null && !src.trim().equalsIgnoreCase("")){ char[] srcChar; srcChar = src.toCharArray(); //汉语拼音格式输出类 HanyuPinyinOutputFormat hanYuPinOutputFormat = new HanyuPinyinOutputFormat(); //输出设置,大小写,音标方式等 hanYuPinOutputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); //小写 hanYuPinOutputFormat.setToneType(HanyuPinyinToneType.WITH_TONE_MARK); //无音调 hanYuPinOutputFormat.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE); //‘¨¹‘ is "v" StringBuffer output = new StringBuffer(); //String[][] temp = new String[src.length()][]; for(int i=0;i<srcChar.length;i++){ char c = srcChar[i]; //是中文转换拼音(我的需求,是保留中文) if(String.valueOf(c).matches("[//u4E00-//u9FA5]+")){ //中文字符 try{ String[] temp = PinyinHelper.toHanyuPinyinStringArray(srcChar[i],hanYuPinOutputFormat); output.append(temp[0]); output.append(" "); }catch(BadHanyuPinyinOutputFormatCombination e){ e.printStackTrace(); } }else{ //其他字符 output.append(String.valueOf(srcChar[i])); } } return output.toString(); } return null; } /** * 只转换汉字为拼音,其他字符不变 * @param src * @return */ public static String getPinyinWithMark2(String inputString){ //汉语拼音格式输出类 HanyuPinyinOutputFormat hanYuPinOutputFormat = new HanyuPinyinOutputFormat(); //输出设置,大小写,音标方式等 hanYuPinOutputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); //小写 hanYuPinOutputFormat.setToneType(HanyuPinyinToneType.WITH_TONE_MARK); //有音调 hanYuPinOutputFormat.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE); //‘¨¹‘ is "u:" char[] input = inputString.trim().toCharArray(); StringBuffer output = new StringBuffer(); for(int i=0;i<input.length;i++){ //是中文转换拼音(我的需求,是保留中文) if(Character.toString(input[i]).matches("[//u4E00-//u9FA5]+")){ //中文字符 try{ String[] temp = PinyinHelper.toHanyuPinyinStringArray(input[i],hanYuPinOutputFormat); output.append(temp[0]); output.append(" "); }catch(BadHanyuPinyinOutputFormatCombination e){ e.printStackTrace(); } }else{ //其他字符 output.append(Character.toString(input[i])); } } return output.toString(); } /** * @param args */ public static void main(String[] args) { String str = "我是中国人! I‘m Chinese!"; //System.out.println(makeStringByStringSet(getPinyin(str)," ")); System.out.println(getPinyinWithMark2(str)+‘??‘); } }
附件:
1.各种拼音说明
Yale Pinyin是在第二次世界大战期间由美国军方发明的编码系统,主要为了让在中国地区作战的美军士兵能够快速地熟悉汉语发音,能够向当地人请求帮助,可以说这是一个速成教材,它的目的甚至不是用来互相交流而是使士兵在发音时不会被中国人听错就可以了。
Gwoyeu Romatzyh:即国语罗马字,它是由林语堂提议建立的,在1928年由国民政府大学堂颁布推行。在中国的台湾省这一编码体系得到了保留,但是它就像 Yale一样现在几乎很少有人使用,在1986年,国语罗马字被国语注音符号第二式(MPSII)所取代,在2002年,又被通用拼音(Tongyong Pinyin)取代,成为台湾今天正式的官方汉语音译编码体系。
威妥玛拼音,习惯称作威妥玛拼法或威玛式拼音、韦氏拼音、威翟式拼音,是一套用于拼写中文普通话的罗马拼音系统。19世纪中叶由英国人威妥玛(Thomas Francis Wade)发明,后由翟理斯(Herbert Allen Giles)完成修订,并编入其所撰写的汉英字典。
参考资料:
1. pinyin4j的官方资料 http://pinyin4j.sourceforge.net/
2. 汉语言的罗马化 http://icookies.spaces.live.com/blog/cns!2CC37E2F87FB3864!170.entry
3. Wiki: 威妥玛拼音(维基百科) http://wapedia.mobi/zh/%E5%A8%81%E5%A6%A5%E7%8E%9B%E6%8B%BC%E9%9F%B3