汉字转拼音PinYinUtil工具类原理解析分享

978 阅读2分钟

需求背景:

 老板希望搞出一款傻瓜工具:将汉字转成拼音,例如 杭州市西湖区-->hangzhoushixihuqu
 或者是 -->hzsxhq
public static void main(String[] args) {
    System.out.println(getFullPinyin("拼音测试数据!!!123"));
    System.out.println(getFullPinyin("拼音测试数据!!!123", false));
    System.out.println(getShortPinyin("拼音测试数据!!!123"));
    System.out.println(getShortPinyin("拼音测试数据!!!123", false));
    System.out.println(getShortPinyin("杭州市西湖区"));
    System.out.println(getShortPinyin("屮"));
}
输出:
 pinyinceshishuju!!!123
 pinyinceshishuju
 pycssj!!!123
 pycssj
 hzsxhq
 c
解决方案:

1 引入转换工具 POM包

<!--拼音中文工具转换类-->
<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-lang3</artifactId>
   <version>3.10</version>
</dependency>

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

核心代码:

2 核心代码

/**
 * 拼音-中文 转换工具类
 */
public class PingYingUtil {

    /**
     * 获取中文拼音首字母,其他字符不变
     *
     * @param str
     * @return String
     */
    public static String getShortPinyin(String str) {
        return getShortPinyin(str, true);
    }

    /**
     * 获取中文拼音首字母
     *
     * @param str
     * @param retain 为true保留其他字符
     * @return String
     */
    public static String getShortPinyin(String str, boolean retain) {
        return getPinyin(str, true, retain);
    }

    /**
     * 获取中文拼音,其他字符不变
     *
     * @param str
     * @return String
     */
    public static String getFullPinyin(String str) {
        return getFullPinyin(str, true);
    }

    /**
     * 获取中文拼音
     *
     * @param str
     * @param retain 为true保留其他字符
     * @return String
     */
    public static String getFullPinyin(String str, boolean retain) {
        return getPinyin(str, false, retain);
    }

    /**
     * 获取中文拼音
     *
     * @param str
     * @param shortPinyin 为true获取中文拼音首字母
     * @param retain      为true保留其他字符
     * @return String
     */
    private static String getPinyin(String str, boolean shortPinyin, boolean retain) {
        if (StringUtils.isBlank(str)) {
            return "";
        }
        StringBuffer pinyinBuffer = new StringBuffer();
        char[] arr = str.toCharArray();
        for (char c : arr) {
            String[] temp = PinyinHelper.toHanyuPinyinStringArray(c);
            if (ArrayUtils.isNotEmpty(temp)) {
                if (StringUtils.isNotBlank(temp[0])) {
                    if (shortPinyin) {
                        pinyinBuffer.append(temp[0].charAt(0));
                    } else {
                        pinyinBuffer.append(temp[0].replaceAll("\d", ""));
                    }
                }
            } else {
                if (retain) {
                    pinyinBuffer.append(c);
                }
            }
        }
        return pinyinBuffer.toString();
    }

源码解析:

 如 杭是如何变成 hang 的?
 核心方法 PinyinHelper.toHanyuPinyinStringArray(c);
    

1 "杭".toCharArray() 转为字符数组 可以看到 杭 对应的十进制 unicode 编码是 26477

1.jpg 2 初始化一个包含 <Unicode, HanyuPinyin> 对的哈希表 也就是初始化 一份关系对应表 /pinyindb/unicode_to_hanyu_pinyin.txt

这里顺便点击进去看看这个表格是什么内容(看到这里应该就差不多了)

2.jpg

3.jpg

3 将杭的十进制 26477 转为16进制--> 676d Integer.toHexString(codePointOfChar).toUpperCase(); image.png

4 根据 步骤2 维护的关系对应表 取出对应的拼音 -->杭--->hang

企业微信截图_6874fa15-1568-414e-9d02-ce9433d08a66.png 5 结束/验证

image.png

思考分析

整个过程其实就是在本地维护了一份 汉字的16进度与其拼音的对应表格,然后取出对应的数据 所以对应的缺点也是有的

例如1 多音字: 银行

public static void main(String[] args) {
    System.out.println(getShortPinyin("银行"));
}
输出:
yx

例如2: 部分汉字依旧会缺失 ***** 但是总体上还是能满足的,有点意思

更多访问杨少的gitHUb