welcome to xlongwei.com

欢迎大家一起学习、交流、分享


QQ:9167702333 邮箱:admin@xlongwei.com

pinyin 拼音接口,支持部分多音字


分类 Java   关键字 分享   标签 java   web   algorithm   发布 hongwei  1449648692154
注意 转载须保留原文链接,译文链接,作者译者等信息。  
pinyin4j支持获取汉字的拼音,对于多音字可以获取到多个拼音结果,还支持多种拼音格式配置。pinyin 拼音接口在pinyin4j的基础上做了接口封装,而多音字的识别使用了额外的多音字库,以后只要完善这个多音字库就可以更准确地识别多音字了。

这里处理caseType,返回拼音数组,以便调用者使用空格或其他字符拼接
/**
* 处理句子
* @param caseType 0-lower 1-camel 2-upper
* @param toneType 0-mark 1-no 2-number
* @param vcharType 0-ü 1-v 2-u: (toneType=0时必须vcharType=0)
*/
public static String[] getPinyin(String sentence, int caseType, int toneType, int vcharType) {
if(toneType!=1 && toneType!=2) vcharType=0; //avoid BadHanyuPinyinOutputFormatCombination
String[] pinyin = new String[sentence.length()];
for(int i=0,len=pinyin.length; i<len; i++) {
String py = getPinyin(sentence, i,
toneType==1?HanyuPinyinToneType.WITHOUT_TONE:(toneType==2?HanyuPinyinToneType.WITH_TONE_NUMBER:HanyuPinyinToneType.WITH_TONE_MARK),
vcharType==1?HanyuPinyinVCharType.WITH_V:(vcharType==2?HanyuPinyinVCharType.WITH_U_AND_COLON:HanyuPinyinVCharType.WITH_U_UNICODE));
if(caseType==1) pinyin[i] = StringUtil.capitalize(py);
else if(caseType==2) pinyin[i] = py.toUpperCase();
else pinyin[i] = py;
}
return pinyin;
}

当获取的拼音有多个时,才检查多音字库,默认返回首个结果
/** 处理多音字,根据上下文选择正确的拼音 */
public static String getPinyin(String sentence, int index, HanyuPinyinToneType toneType, HanyuPinyinVCharType vcharType) {
String[] pinyin = getPinyin(sentence.charAt(index), toneType, vcharType);
if(pinyin.length>1) {//多音字处理,多音字库保存的拼音是:小写,无声调,v样式,所以要与这种样式的拼音对比
String[] pinyins = ((toneType==null||toneType==HanyuPinyinToneType.WITHOUT_TONE)&&(vcharType==null||vcharType==HanyuPinyinVCharType.WITH_V)) ? pinyin : getPinyin(sentence.charAt(index), HanyuPinyinToneType.WITHOUT_TONE, HanyuPinyinVCharType.WITH_V);
List<String> words = new ArrayList<>(); int left = Math.max(index - duoyinziMax + 1, 0), len = sentence.length();
for(int i=left; i<=index; i++) { //这两个for循环的算法比较复杂,找出包含index字符的duoyinziMax以内个数的所有组合
for(int j=Math.max(index, i+1); j<Math.min(i+duoyinziMax,len); j++) {//由于没有分词算法的支持,所以只能穷举了
words.add(sentence.substring(i, j+1));
}
} words.add(sentence.substring(index.index+1));
for(String word : words) {
String py = duoyinzi.get(word);
if(py!=null) {
int i = ArrayUtils.indexOf(pinyins, py);//找到多音字的某个拼音位置
if(i>-1) return pinyin[i]; //返回相应位置的正确格式化的拼音
}
}
}
return pinyin[0];
}

获取汉字的一个或多个拼音,默认原样返回
/** 处理单子拼音,多音字有多个 */
public static String[] getPinyin(char ch, HanyuPinyinToneType toneType, HanyuPinyinVCharType vcharType) {
try {
if(ch=='\u3007' || (ch>='\u4e00'&&ch<='\u9fa5')) {//不处理英文、标点等非汉字字符
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setToneType(toneType!=null ? toneType : HanyuPinyinToneType.WITHOUT_TONE);
format.setVCharType(vcharType!=null ? vcharType : HanyuPinyinVCharType.WITH_V);
String[] pinyin = PinyinHelper.toHanyuPinyinStringArray(ch, format);
if(pinyin!=null && pinyin.length>0) return pinyin;//结果可能为null,返回原值
}
} catch (BadHanyuPinyinOutputFormatCombination e) {}
return new String[] {String.valueOf(ch)};
}

多音字库加载
private static final Map<String, String> duoyinzi = new HashMap<>();
private static int duoyinziMax = 1;
static {
try {
List<String> lines = IOUtils.readLines(PinyinUtil.class.getResourceAsStream("/duoyinzi.txt"), Charsets.UTF_8);
for(String line : lines) {
String[] split = line.split("#");//格式:ao#拗口 违拗 凹
String[] words = split[1].split(" ");
for(String word:words) {
duoyinzi.put(word, split[0]);
if(word.length()>duoyinziMax) duoyinziMax = word.length();
}
}
logger.info("duoyinzi words: "+duoyinzi.size()+", max length: "+duoyinziMax);//duoyinziMax关系到句子中汉字的上下文切割
} catch (IOException e) {
logger.warn("fail to load duoyinzi.txt: "+e.getMessage());
}
}

demo地址:http://cms.xlongwei.com/demo/pinyin.html
showapi接口地址:https://www.showapi.com/api/lookPoint/874
参考代码:PinyinUtilOpenController多音字库,