/* * JEF - Copyright 2009-2010 Jiyi (mr.jiyi@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jef.tools.chinese; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import jef.tools.ArrayUtils; 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; /** * 汉字拼音工具,使用pinyin4j(需要第三方包)。 * <p> * pinyin4j支持将汉字转化成六种拼音表示法。其对应关系是: * <table width="90%" border=1> * <tr> * <td><b>汉语拼音-Hanyu Pinyin</b></td> * <td><b>即现在大陆主流的汉语拼音</b></td> * </tr> * <tr> * <td>通用拼音-Tongyong Pinyin</td> * <td>台湾现在正式的官方汉语音译编码</td> * </tr> * <tr> * <td>威妥玛拼音(威玛拼法)-Wade-Giles Pinyin</td> * <td>19世纪中叶由英国人威妥玛(Thomas Francis Wade)发明,后由翟理斯(Herbert Allen * Giles)完成修订,并编入其所撰写的汉英字典</td> * </tr> * <tr> * <td>注音符号第二式-MPSII Pinyin</td> * <td>国语注音符号,台湾地区的主流注音方式</td> * </tr> * <tr> * <td>耶鲁拼法-Yale Pinyin</td> * <td>第二次世界大战期间由美国军方发明的编码系统,主要为了让在中国地区作战的美军士兵能够快速地熟悉汉语发音,很少人用</td> * </tr> * <tr> * <td>国语罗马字-Gwoyeu Romatzyh。</td> * <td>国语罗马字,它是由林语堂提议建立的,在1928年由国民政府大学堂颁布推行,很少人用</td> * </tr> * </table> * <p> * <h3>关于输出格式:</h3> * 声调选项 * <ul> * <li> WITH_TONE_NUMBER(以数字代替声调) : zhong1 zhong4</li> * <li>WITHOUT_TONE * (无声调) : zhong zhong </li> * <li>WITH_TONE_MARK (有声调) : zhōng zhòng (需要用unicode支持)</li> * </ul> * u v u(上两点)的的表示方式,以‘吕’的输出为例 * <ul> * <li>WITH_U_AND_COLON : lu:3 (u加上冒号)</li> * <li>WITH_V : lv3 * (用v表示u上两点,符合现行输入法习惯) </li> * <li>WITH_U_UNICODE : lü3 (用unocide的U上两点符号)</li> * </ul> * <p> * 此功能需要依赖第三方包pinyin4j。 * * @author Jiyi * */ public class PinyinUtil { /** * 默认输出格式: 小写、用v表示ü的拼音、无声调。 */ private static final HanyuPinyinOutputFormat FORMAT_DEFAULT = new HanyuPinyinOutputFormat(); /** * 输出格式:带声调,用数字1,2,3,4表示声调的阴平、阳平、上声、去声,无数字表示轻声。 */ private static final HanyuPinyinOutputFormat FORMAT_WITH_TONE = new HanyuPinyinOutputFormat(); static{ //设置默认输出格式 FORMAT_DEFAULT.setCaseType(HanyuPinyinCaseType.LOWERCASE); FORMAT_DEFAULT.setToneType(HanyuPinyinToneType.WITHOUT_TONE); FORMAT_DEFAULT.setVCharType(HanyuPinyinVCharType.WITH_V); FORMAT_WITH_TONE.setVCharType(HanyuPinyinVCharType.WITH_V); } /** * 将指定字符串转为拼音 * * @param source 字符串。 * @return 拼音。英文字符不变。多个汉字的拼音之间没有分隔。 */ public static String getPinyin(String source){ return getPinyin(source,""); } /** * 将指定字符串转为拼音 * * @param source 字符串 * @param sep 每个汉字拼音之间的分隔符 * @return 拼音。英文字符不变。多个汉字的拼音之间用指定的字符分隔 */ @SuppressWarnings("deprecation") public static String getPinyin(String source,String sep){ try { return PinyinHelper.toHanyuPinyinString(source, FORMAT_DEFAULT, sep); } catch (BadHanyuPinyinOutputFormatCombination e) { throw new IllegalArgumentException(e.getMessage()); } } static class PinyinResult{ String result; final LinkedList<String> afterResult=new LinkedList<String>(); PinyinResult parent; public PinyinResult(String s,PinyinResult parent) { this.result=s; this.parent=parent; } public void add(String newPinyin){ afterResult.addFirst(newPinyin); } public List<PinyinResult> add(String[] newPinyin){ if(newPinyin.length>1){ List<PinyinResult> children=new ArrayList<PinyinResult>(3); for(String s:newPinyin){ PinyinResult choise=new PinyinResult(s,this); children.add(choise); } return children; } throw new IllegalArgumentException(); } public String compute(String sep) { List<String> path=new ArrayList<String>(); PinyinResult obj=this; while(obj.parent!=null){ path.addAll(obj.afterResult); path.add(obj.result); obj=obj.parent; } path.addAll(obj.afterResult); StringBuilder sb=new StringBuilder(); for(int i=path.size()-1;i>=0;i--){ sb.append(path.get(i)).append(sep); } return sb.toString(); } } /** * 将指定字符串转为拼音,如果有多音字列出所有组合 * * @param src 要转换的文字 * @return 拼音,原文中的英文不变 * @throws */ public static String[] getAllPingYin(String src) { return getAllPingYin(src," "); } /** * 将指定字符串转为拼音,如果有多音字列出所有组合 * * @param src 要转换的文字 * @param sep 分隔符 * @return 拼音,原文中的英文不变 * @throws */ public static String[] getAllPingYin(String src,String sep) { PinyinResult root=new PinyinResult(null,null);//根节点 List<PinyinResult> lastLeaves=new ArrayList<PinyinResult>(); lastLeaves.add(root); try { StringBuilder english=new StringBuilder(); for (int i = 0; i < src.length(); i++) { char c=src.charAt(i); String[] pinyin = PinyinHelper.toHanyuPinyinStringArray(c, FORMAT_DEFAULT); if(pinyin==null){ english.append(c); continue; } if(english.length()>0){ String s=english.toString(); english.setLength(0); for(PinyinResult r:lastLeaves){ r.add(s); } } if(pinyin.length>1){ pinyin=ArrayUtils.removeDups(pinyin); } if(pinyin.length==1){ for(PinyinResult r:lastLeaves){ r.add(pinyin[0]); } }else{ List<PinyinResult> newleaves=new ArrayList<PinyinResult>(); for(PinyinResult pinyinLeaf:lastLeaves){ newleaves.addAll(pinyinLeaf.add(pinyin)); } lastLeaves=newleaves; } } //将所有拼音的组合构成一棵树 List<String> results=new ArrayList<String>(lastLeaves.size()); for(PinyinResult pinyin:lastLeaves){ results.add(pinyin.compute(sep)); } return results.toArray(new String[results.size()]); } catch (BadHanyuPinyinOutputFormatCombination ex) { throw new IllegalArgumentException(ex.getMessage()); } } /** * 返回中文的首字母 */ public static String getPinYinHeadChar(String str) { StringBuilder convert = new StringBuilder(); for (int j = 0; j < str.length(); j++) { char c = str.charAt(j); String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c); if (pinyinArray != null) { convert.append(pinyinArray[0].charAt(0)); } else { convert.append(c); } } return convert.toString(); } }