專案常需「中文轉拼音」功能 (搜尋提示、排序、檔名轉碼)。主流開源庫 pinyin4j (Maven: com.belerweb:pinyin4j:2.5.0) 提供完整漢字拼音支援,含多音字、聲調、大小寫、v/ü 處理。本文封裝可直接生產使用的工具類。
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>2.5.0</version>
</dependency>
import net.sourceforge.pinyin4j.*;
import net.sourceforge.pinyin4j.format.*;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
public final class PinyinUtils {
private PinyinUtils() {}
/** 全拼 (小寫、無聲調、v 代替 ü) */
public static String toFullPinyin(String chinese) {
if (chinese == null || chinese.isEmpty()) return "";
HanyuPinyinOutputFormat fmt = defaultFormat();
StringBuilder sb = new StringBuilder(chinese.length() * 3);
for (char c : chinese.toCharArray()) {
if (isChinese(c)) {
try {
String[] pys = PinyinHelper.toHanyuPinyinStringArray(c, fmt);
sb.append(pys != null && pys.length > 0 ? pys[0] : c); // 取首個讀音
} catch (BadHanyuPinyinOutputFormatCombination e) {
sb.append(c);
}
} else {
sb.append(c); // 非漢字原樣保留
}
}
return sb.toString();
}
/** 首字母縮寫 (大寫) */
public static String toInitials(String chinese) {
if (chinese == null || chinese.isEmpty()) return "";
StringBuilder sb = new StringBuilder(chinese.length());
for (char c : chinese.toCharArray()) {
if (isChinese(c)) {
String[] pys = PinyinHelper.toHanyuPinyinStringArray(c);
sb.append(pys != null && pys.length > 0 ? Character.toUpperCase(pys[0].charAt(0)) : c);
} else {
sb.append(Character.toUpperCase(c));
}
}
return sb.toString();
}
/** GBK/UTF-8 位元組轉十六進位字串 (舊系統相容) */
public static String toHexBytes(String str, String charset) {
try {
byte[] bytes = str.getBytes(charset);
StringBuilder sb = new StringBuilder(bytes.length * 2);
for (byte b : bytes) sb.append(String.format("%02X", b));
return sb.toString();
} catch (Exception e) { return ""; }
}
private static HanyuPinyinOutputFormat defaultFormat() {
HanyuPinyinOutputFormat fmt = new HanyuPinyinOutputFormat();
fmt.setCaseType(HanyuPinyinCaseType.LOWERCASE);
fmt.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
fmt.setVCharType(HanyuPinyinVCharType.WITH_V); // ü → v
return fmt;
}
private static boolean isChinese(char c) {
return Character.UnicodeBlock.of(c) == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS;
}
// 測試
public static void main(String[] args) {
String s = "中國";
System.out.println("全拼: " + toFullPinyin(s)); // zhongguo
System.out.println("首字母: " + toInitials(s)); // ZG
System.out.println("UTF-8 Hex: " + toHexBytes(s, "UTF-8")); // E4B8ADE59CB8
}
}
| 設定 | 選項 | 範例 (中國) |
|---|---|---|
| 大小寫 | LOWERCASE / UPPERCASE | zhongguo / ZHONGGUO |
| 聲調 | WITH_TONE_NUMBER (1-4) / WITH_TONE_MARK (āáǎà) / WITHOUT_TONE | zhong1guo2 / zhōngguó / zhongguo |
| ü 處理 | WITH_V (v) / WITH_U_AND_COLON (u:) / WITH_U_UNICODE (ü) | lv / lu: / lü |
toHanyuPinyinStringArray 回傳所有可能讀音。工具類採用 **首個讀音** 策略 (最常用)。若需精確,需結合詞典/分詞庫 (如 HanLP、jieba) 依上下文消歧。
ConcurrentHashMap 或 Guava Cache 緩存。HanyuPinyinOutputFormat,共用單例。com.github.stuxuhai:jpinyin (更輕量)、com.hankcs:hanlp (含分詞、NER、依存分析)。Character.UnicodeBlock 判斷需擴展至 CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A/B/C/D。PinyinHelper 靜態方法無狀態,安全;HanyuPinyinOutputFormat 非線程安全,**勿共用實例於多線程修改**,建議方法內 new 或 ThreadLocal。