Pinyin4j 汉语拼音处理库

1,264 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情

Pinyin4j

Pinyin4j 是一个流行的 Java 库,支持中文字符和拼音之间的转换,可以自主的控制转换拼音的格式,在我们日常开发的项目中,经常会遇到汉字转拼音,或者拼音搜索的场景,这时候使用 Pinyin4j 即可快速解决这个需求。

如何使用

依赖

需要引入依赖如下:

<dependency>
  <groupId>com.belerweb</groupId>
  <artifactId>pinyin4j</artifactId>
  <version>2.5.0</version>
</dependency>

拼音格式化

Pinyin4j 采用 HanyuPinyinOutputFormat 对象来设置拼音的格式。

大小写转化

使用如下代码进行大小写转换:

outputFormat.setCaseType(HanyuPinyinCaseType);

支持两种方式:

  • HanyuPinyinCaseType.LOWERCASE 拼音小写输出
  • HanyuPinyinCaseType.UPPERCASE 拼音大写输出
拼音声调格式转化

使用如下代码,显示拼音的声调:

outputFormat.setToneType(HanyuPinyinToneType);

支持如下几种方式:

  • HanyuPinyinToneType.WITH_TONE_NUMBER 用数字表示声调
  • HanyuPinyinToneType.WITHOUT_TONE 无声调表示
  • HanyuPinyinToneType.WITH_TONE_MARK 用声调符号表示
特殊拼音 ü 的显示格式

比如: 汉字 绿 在拼音输入法中,用 y v 两键来输入.

拼音 u 和 ü 的区别:

  • u 发 wu 音,ü 发 yu 音

  • ü 在键盘上没有,用 v 代替

  • ü 的上方有标声符号的时候, 要省略上边的两点 用 u 而不用 ü

使用如下代码进行设置:

outputFormat.setVCharType(HanyuPinyinVCharType);

支持如下几种方式:

  • HanyuPinyinVCharType.WITH_U_AND_COLONu: 表示

  • HanyuPinyinVChazType.WITH_Vv 表示

  • HanyuPinyinVCharType.WITH_U_UNICODEü 表示

PingYinUtil 工具类

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 PingYinUtil {

    public static void main(String[] args) {
        String res = getFullSpell("绿色");
        System.out.println(res);			// lu:se
        String res2 = getFullSpell2("绿色");
        System.out.println(res2);			// lvse
    }

    public static String getAlphabetic(String str) {
        //接收字符串中的单个字符
        char[] alphabeticArray = str.toCharArray();
        //声明字符串数组用于接收单个汉字的拼音
        String[] singleChinese;
        //拼音格式对象,用于设置拼音格式
        HanyuPinyinOutputFormat hanyuPinyinOutputFormat = new HanyuPinyinOutputFormat();
        hanyuPinyinOutputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        hanyuPinyinOutputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        hanyuPinyinOutputFormat.setVCharType(HanyuPinyinVCharType.WITH_V);
        StringBuilder result = new StringBuilder();
        try {
            //遍历每个字符
            for (int i = 0; i < alphabeticArray.length; i++) {
                //判断当前字符是否为汉字
                // 中文的 unicode 编码范围:第一个“4e00”,最后一个“9fa5”
                if (Character.toString(alphabeticArray[i]).matches("[\u4E00-\u9FA5]+")) {
                    // 这里返回的是数组,因为这个汉字可能是多音字,会返回所有读音
                    singleChinese = PinyinHelper.toHanyuPinyinStringArray(alphabeticArray[i], hanyuPinyinOutputFormat);
                    if (singleChinese != null && singleChinese.length > 0) {
                        if (singleChinese.length == 1) {
                            result.append(singleChinese[0]);
                        } else {
                            // 多个读音的话,根据需要取获取吧
                            result.append(singleChinese[0]);
                        }
                    }
                } else {
                    result.append(alphabeticArray[i]);
                }
            }
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            e.printStackTrace();
        }
        return result.toString();
    }

    /**
     * 获取汉字串拼音,英文字符不变
     * @param chinese 汉字串
     * @return 汉语拼音
     */
    public static String getFullSpell(String chinese) {
        StringBuffer result = new StringBuffer();
        char[] arr = chinese.toCharArray();
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);       // 转为拼音时,小写
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);    // 不获取声调
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] > 128) {
                try {
                    result.append(PinyinHelper.toHanyuPinyinStringArray(arr[i], defaultFormat)[0]);
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    e.printStackTrace();
                }
            } else {
                result.append(arr[i]);
            }
        }
        return result.toString();
    }

    /**
     * 获取汉字串拼音,英文字符不变
     * @param chinese 汉字串
     * @return 汉语拼音
     */
    public static String getFullSpell2(String chinese) {
        StringBuffer result = new StringBuffer();
        char[] arr = chinese.toCharArray();
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);       // 转为拼音时,小写
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);    // 不获取声调
        defaultFormat.setVCharType(HanyuPinyinVCharType.WITH_V);        // 特殊字母处理
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] > 128) {
                try {
                    result.append(PinyinHelper.toHanyuPinyinStringArray(arr[i], defaultFormat)[0]);
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    e.printStackTrace();
                }
            } else {
                result.append(arr[i]);
            }
        }
        return result.toString();
    }
}

多音字的处理

Pinyin4j 是没有办法识别多音字的,比如输入 "成都" 得到的结果却是 "ChengDou",emmm,很明显,在 成都 这个词汇中,都 应该是 du 音 而不是 dou 音。

Pinyin4j 对于多音字,会返回所有的读音,是一个数组,而它默认读取的是第一个音来作为该字的拼音。

找到了两种解决方法:

这种方式其实比较笨,就是将 成都 放到一个文件中,然后 Pinyin4j 去处理输入的时候,看文件中有没有这个词,然后使用文件中规定的拼音。看着很美好,但是工作量比较大。

换了另一个工具去实现,还没有用过,不知道效果如何。