汉字转拼音工具使用 Jpinyin和PinYin4J

一.介绍

pinyin4j是一个开源的java库(官网地址:http://pinyin4j.sourceforge.net/),使用来处理中文转换成拼音(汉语拼音,罗马拼音等),功能强大。

特点:

  1. 支持简体中文和繁体中文字符
  2. 支持转换汉语拼音,威玛拼音,耶鲁拼法
  3. 支持多音字,可获取一个字符的多个发音
  4. 支持多种拼音格式输出

JPinyin是一个汉字转拼音的Java开源类库,在PinYin4j的功能基础上做了一些改进。

特点:
1、准确、完善的字库;
        Unicode编码从4E00-9FA5范围及3007(〇)的20903个汉字中,JPinyin能转换除46个异体字(异体字不存在标准拼音)之外的所有汉字;
2、拼音转换速度快;
        经测试,转换Unicode编码从4E00-9FA5范围的20902个汉字,JPinyin耗时约100毫秒。
3、多拼音格式输出支持;
        JPinyin支持多种拼音输出格式:带音标、不带音标、数字表示音标以及拼音首字母输出格式;
4、常见多音字识别;
        JPinyin支持常见多音字的识别,其中包括词组、成语、地名等;
5、简繁体中文转换

使用PinYin4j开源项目获取汉字的拼音,需要对多音字手动配置,添加字典配置,将可能出现的多音字 词组组合起来,用正确拼音当作其key,词组当作value,保存到一个Map集合中。使用PinYin4j获取汉字拼音时判断是否为多音字(返回数组的 长度大于1),如果为多音字,用其拼音去 Map集合中查找,若有则取当前拼音为正确拼音。若到最后都没有找到,给其一个默认的拼音。详见参考案例

而JPinyin项目中已经内置了将生字、词组和对应的拼音以及简繁汉字对应的数据库,然后通过代码操作数据库来实现汉字/词组转拼音和汉字简繁互转的,数据库都是加密的,虽然不能扩充,但这个工具已经比较完善了,基本都可以满足需求.

二.简单使用

pinyin4j 常用的类:

  1.  PinyinHelper:提供了几个实用程序函数,用于将中文字符(简体和繁体)转换为拼音
  2.  HanyuPinyinCaseType:设置输出字符大小写
  3.  HanyuPinyinOutputFormat:设置输出的格式化方式
  4.  HanyuPinyinToneType:设置输出中文音调的选项
  5.  HanyuPinyinVCharType;设置字符'ü'的展示方式
String[] strings = new String[]{"重庆", "厦门", "长沙", "台州","绿色","海水朝朝朝朝朝朝朝落,浮云长长长长长长长消"};

        //pingyin4j
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        format.setToneType(HanyuPinyinToneType.WITH_TONE_NUMBER);//设置声调
        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);//大小写
        format.setVCharType(HanyuPinyinVCharType.WITH_U_AND_COLON);

        Arrays.stream(strings).forEachOrdered(s -> {
            try {
                String pinyin = net.sourceforge.pinyin4j.PinyinHelper.toHanYuPinyinString(s,format," ",true);
                System.err.println(s + ":" + pinyin);
            } catch (BadHanyuPinyinOutputFormatCombination e) {
                e.printStackTrace();
            }
        });

Jpinyin里面一共有四个类:

  1. ChineseHelper: 汉字简繁体转换类,提供常用方法
  2. PinyinFormat:设置输出的格式化方式
  3. PinyinHelper:汉字转拼音类,提供常用方法
  4. PinyinResource:资源文件加载类
    Arrays.stream(strings).forEachOrdered(s -> {
                try {
                    String pinyin = PinyinHelper.convertToPinyinString(s," ",PinyinFormat.WITH_TONE_NUMBER);
                    System.err.println(s + ":" + pinyin);
                } catch (PinyinException e) {
                    e.printStackTrace();
                }
            });

    输出结果:

    运行结果

     

相比较 Jpinyin在pinyin4j的基础上改善了易用性,对词汇的多音字的识别也更好.推荐使用Jpinyin

最后附上Jpinyin的PinyinHelper源码

/**
 * 汉字转拼音类
 *
 * @author stuxuhai (dczxxuhai@gmail.com)
 */
public final class PinyinHelper {
	private static List<String> dict = new ArrayList<String>();
	private static final Map<String, String> PINYIN_TABLE = PinyinResource.getPinyinResource();
	private static final Map<String, String> MUTIL_PINYIN_TABLE = PinyinResource.getMutilPinyinResource();
	private static final DoubleArrayTrie DOUBLE_ARRAY_TRIE = new DoubleArrayTrie();
	private static final String PINYIN_SEPARATOR = ","; // 拼音分隔符
	private static final char CHINESE_LING = '〇';
	private static final String ALL_UNMARKED_VOWEL = "aeiouv";
	private static final String ALL_MARKED_VOWEL = "āáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜ"; // 所有带声调的拼音字母

	static {
		for (String word : MUTIL_PINYIN_TABLE.keySet()) {
			dict.add(word);
		}
		Collections.sort(dict);
		DOUBLE_ARRAY_TRIE.build(dict);
	}

	private PinyinHelper() {
	}

	/**
	 * 将带声调格式的拼音转换为数字代表声调格式的拼音
	 * 
	 * @param pinyinArrayString
	 *            带声调格式的拼音
	 * @return 数字代表声调格式的拼音
	 */
	private static String[] convertWithToneNumber(String pinyinArrayString) {
		String[] pinyinArray = pinyinArrayString.split(PINYIN_SEPARATOR);
		for (int i = pinyinArray.length - 1; i >= 0; i--) {
			boolean hasMarkedChar = false;
			String originalPinyin = pinyinArray[i].replace("ü", "v"); // 将拼音中的ü替换为v

			for (int j = originalPinyin.length() - 1; j >= 0; j--) {
				char originalChar = originalPinyin.charAt(j);

				// 搜索带声调的拼音字母,如果存在则替换为对应不带声调的英文字母
				if (originalChar < 'a' || originalChar > 'z') {
					int indexInAllMarked = ALL_MARKED_VOWEL.indexOf(originalChar);
					int toneNumber = indexInAllMarked % 4 + 1; // 声调数
					char replaceChar = ALL_UNMARKED_VOWEL.charAt((indexInAllMarked - indexInAllMarked % 4) / 4);
					pinyinArray[i] = originalPinyin.replace(String.valueOf(originalChar), String.valueOf(replaceChar))
							+ toneNumber;
					hasMarkedChar = true;
					break;
				}
			}
			if (!hasMarkedChar) {
				// 找不到带声调的拼音字母说明是轻声,用数字5表示
				pinyinArray[i] = originalPinyin + "5";
			}
		}

		return pinyinArray;
	}

	/**
	 * 将带声调格式的拼音转换为不带声调格式的拼音
	 * 
	 * @param pinyinArrayString
	 *            带声调格式的拼音
	 * @return 不带声调的拼音
	 */
	private static String[] convertWithoutTone(String pinyinArrayString) {
		String[] pinyinArray;
		for (int i = ALL_MARKED_VOWEL.length() - 1; i >= 0; i--) {
			char originalChar = ALL_MARKED_VOWEL.charAt(i);
			char replaceChar = ALL_UNMARKED_VOWEL.charAt((i - i % 4) / 4);
			pinyinArrayString = pinyinArrayString.replace(String.valueOf(originalChar), String.valueOf(replaceChar));
		}
		// 将拼音中的ü替换为v
		pinyinArray = pinyinArrayString.replace("ü", "v").split(PINYIN_SEPARATOR);
		return pinyinArray;
	}

	/**
	 * 将带声调的拼音格式化为相应格式的拼音
	 * 
	 * @param pinyinString
	 *            带声调的拼音
	 * @param pinyinFormat
	 *            拼音格式:WITH_TONE_NUMBER--数字代表声调,WITHOUT_TONE--不带声调,WITH_TONE_MARK--带声调
	 * @return 格式转换后的拼音
	 */
	private static String[] formatPinyin(String pinyinString, PinyinFormat pinyinFormat) {
		if (pinyinFormat == PinyinFormat.WITH_TONE_MARK) {
			return pinyinString.split(PINYIN_SEPARATOR);
		} else if (pinyinFormat == PinyinFormat.WITH_TONE_NUMBER) {
			return convertWithToneNumber(pinyinString);
		} else if (pinyinFormat == PinyinFormat.WITHOUT_TONE) {
			return convertWithoutTone(pinyinString);
		}
		return new String[0];
	}

	/**
	 * 将单个汉字转换为相应格式的拼音
	 * 
	 * @param c
	 *            需要转换成拼音的汉字
	 * @param pinyinFormat
	 *            拼音格式:WITH_TONE_NUMBER--数字代表声调,WITHOUT_TONE--不带声调,WITH_TONE_MARK--带声调
	 * @return 汉字的拼音
	 */
	public static String[] convertToPinyinArray(char c, PinyinFormat pinyinFormat) {
		String pinyin = PINYIN_TABLE.get(String.valueOf(c));
		if ((pinyin != null) && (!"null".equals(pinyin))) {
			Set<String> set = new LinkedHashSet<String>();
			for (String str : formatPinyin(pinyin, pinyinFormat)) {
				set.add(str);
			}
			return set.toArray(new String[set.size()]);
		}
		return new String[0];
	}

	/**
	 * 将单个汉字转换成带声调格式的拼音
	 * 
	 * @param c
	 *            需要转换成拼音的汉字
	 * @return 字符串的拼音
	 */
	public static String[] convertToPinyinArray(char c) {
		return convertToPinyinArray(c, PinyinFormat.WITH_TONE_MARK);
	}

	/**
	 * 将字符串转换成相应格式的拼音
	 * 
	 * @param str
	 *            需要转换的字符串
	 * @param separator
	 *            拼音分隔符
	 * @param pinyinFormat
	 *            拼音格式:WITH_TONE_NUMBER--数字代表声调,WITHOUT_TONE--不带声调,WITH_TONE_MARK--带声调
	 * @return 字符串的拼音
	 * @throws PinyinException
	 */
	public static String convertToPinyinString(String str, String separator, PinyinFormat pinyinFormat)
			throws PinyinException {
		str = ChineseHelper.convertToSimplifiedChinese(str);
		StringBuilder sb = new StringBuilder();
		int i = 0;
		int strLen = str.length();
		while (i < strLen) {
			String substr = str.substring(i);
			List<Integer> commonPrefixList = DOUBLE_ARRAY_TRIE.commonPrefixSearch(substr);
			if (commonPrefixList.size() == 0) {
				char c = str.charAt(i);
				// 判断是否为汉字或者〇
				if (ChineseHelper.isChinese(c) || c == CHINESE_LING) {
					String[] pinyinArray = convertToPinyinArray(c, pinyinFormat);
					if (pinyinArray != null) {
						if (pinyinArray.length > 0) {
							sb.append(pinyinArray[0]);
						} else {
							throw new PinyinException("Can't convert to pinyin: " + c);
						}
					} else {
						sb.append(str.charAt(i));
					}
				} else {
					sb.append(c);
				}
				i++;
			} else {
				String words = dict.get(commonPrefixList.get(commonPrefixList.size() - 1));
				String[] pinyinArray = formatPinyin(MUTIL_PINYIN_TABLE.get(words), pinyinFormat);
				for (int j = 0, l = pinyinArray.length; j < l; j++) {
					sb.append(pinyinArray[j]);
					if (j < l - 1) {
						sb.append(separator);
					}
				}
				i += words.length();
			}

			if (i < strLen) {
				sb.append(separator);
			}
		}
		return sb.toString();
	}

	/**
	 * 将字符串转换成带声调格式的拼音
	 * 
	 * @param str
	 *            需要转换的字符串
	 * @param separator
	 *            拼音分隔符
	 * @return 转换后带声调的拼音
	 * @throws PinyinException
	 */
	public static String convertToPinyinString(String str, String separator) throws PinyinException {
		return convertToPinyinString(str, separator, PinyinFormat.WITH_TONE_MARK);
	}

	/**
	 * 判断一个汉字是否为多音字
	 * 
	 * @param c
	 *            汉字
	 * @return 判断结果,是汉字返回true,否则返回false
	 */
	public static boolean hasMultiPinyin(char c) {
		String[] pinyinArray = convertToPinyinArray(c);
		if (pinyinArray != null && pinyinArray.length > 1) {
			return true;
		}
		return false;
	}

	/**
	 * 获取字符串对应拼音的首字母
	 * 
	 * @param str
	 *            需要转换的字符串
	 * @return 对应拼音的首字母
	 * @throws PinyinException
	 */
	public static String getShortPinyin(String str) throws PinyinException {
		String separator = "#"; // 使用#作为拼音分隔符
		StringBuilder sb = new StringBuilder();

		char[] charArray = new char[str.length()];
		for (int i = 0, len = str.length(); i < len; i++) {
			char c = str.charAt(i);

			// 首先判断是否为汉字或者〇,不是的话直接将该字符返回
			if (!ChineseHelper.isChinese(c) && c != CHINESE_LING) {
				charArray[i] = c;
			} else {
				int j = i + 1;
				sb.append(c);

				// 搜索连续的汉字字符串
				while (j < len && (ChineseHelper.isChinese(str.charAt(j)) || str.charAt(j) == CHINESE_LING)) {
					sb.append(str.charAt(j));
					j++;
				}
				String hanziPinyin = convertToPinyinString(sb.toString(), separator, PinyinFormat.WITHOUT_TONE);
				String[] pinyinArray = hanziPinyin.split(separator);
				for (String string : pinyinArray) {
					charArray[i] = string.charAt(0);
					i++;
				}
				i--;
				sb.setLength(0);
			}
		}
		return String.valueOf(charArray);
	}

	public static void addPinyinDict(String path) throws FileNotFoundException {
		PINYIN_TABLE.putAll(PinyinResource.getResource(PinyinResource.newFileReader(path)));
	}

	public static void addMutilPinyinDict(String path) throws FileNotFoundException {
		MUTIL_PINYIN_TABLE.putAll(PinyinResource.getResource(PinyinResource.newFileReader(path)));
		dict.clear();
		DOUBLE_ARRAY_TRIE.clear();
		for (String word : MUTIL_PINYIN_TABLE.keySet()) {
			dict.add(word);
		}
		Collections.sort(dict);
		DOUBLE_ARRAY_TRIE.build(dict);
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值