判斷字串是否包含中文、英文、標點等字符類型,常見於輸入驗證、文本統計、敏感詞過濾等場景。單純用正則 [\u4e00-\u9fa5] 只覆蓋基本漢字區,無法識別擴展區、兼容區、標點符號等。本文提供基於 Character.UnicodeBlock 的完整解決方案。
public static void identifyCharBlock(char c) {
Character.UnicodeBlock block = Character.UnicodeBlock.of(c);
if (block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS) {
System.out.println(c + " -> 基本漢字區 (CJK Unified Ideographs)");
} else if (block == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS) {
System.out.println(c + " -> 兼容漢字區");
} else if (block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A) {
System.out.println(c + " -> 擴展區 A");
} else if (block == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
System.out.println(c + " -> 通用標點");
} else if (block == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION) {
System.out.println(c + " -> CJK 標點符號");
} else if (block == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
System.out.println(c + " -> 半形/全形形式");
}
// 可繼續擴展:Extension B/C/D/E/F, Kangxi Radicals, Bopomofo 等
}
public static boolean containsChinese(String str) {
if (str == null || str.isEmpty()) return false;
for (char c : str.toCharArray()) {
Character.UnicodeBlock block = Character.UnicodeBlock.of(c);
if (block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS ||
block == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS ||
block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A ||
block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B ||
block == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION ||
block == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
return true;
}
}
return false;
}
// 正則替代方案(僅基本漢字區)
public static boolean containsChineseRegex(String str) {
return str != null && str.matches(".*[\\u4E00-\\u9FA5].*");
}
public static boolean isPureEnglish(String str) {
return str != null && str.matches("^[a-zA-Z]*$");
}
// 允許數字、底線、空格
public static boolean isEnglishAlphanumeric(String str) {
return str != null && str.matches("^[a-zA-Z0-9_\\s]*$");
}
public static Map countCharTypes(String str) {
Map counts = new HashMap<>();
counts.put("chinese", 0);
counts.put("english", 0);
counts.put("digit", 0);
counts.put("punctuation", 0);
counts.put("other", 0);
for (char c : str.toCharArray()) {
if (Character.isDigit(c)) counts.merge("digit", 1, Integer::sum);
else if (Character.isLetter(c)) {
Character.UnicodeBlock block = Character.UnicodeBlock.of(c);
if (isChineseBlock(block)) counts.merge("chinese", 1, Integer::sum);
else counts.merge("english", 1, Integer::sum);
} else if (isPunctuationBlock(Character.UnicodeBlock.of(c))) {
counts.merge("punctuation", 1, Integer::sum);
} else {
counts.merge("other", 1, Integer::sum);
}
}
return counts;
}
private static boolean isChineseBlock(Character.UnicodeBlock block) {
return block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS ||
block == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS ||
block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A ||
block == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B ||
block == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION;
}
private static boolean isPunctuationBlock(Character.UnicodeBlock block) {
return block == Character.UnicodeBlock.GENERAL_PUNCTUATION ||
block == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION;
}
public static void main(String[] args) {
String test = "我愛你,!?():;“”、。China123";
char[] chars = test.toCharArray();
for (char c : chars) identifyCharBlock(c);
System.out.println("包含中文: " + containsChinese("中國god damn")); // true
System.out.println("純英文: " + isPureEnglish("dfafdabac")); // true
System.out.println("字符統計: " + countCharTypes(test));
// 輸出: {chinese=10, english=5, digit=3, punctuation=10, other=0}
}
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| UnicodeBlock 逐字檢查 | 精準、支援所有 Unicode 區塊、可統計分類 | 效能較低(逐字循環)、代碼較多 | 精準識別、多語言混排分析、合規檢查 |
| 正則表達式 | 簡潔、效能高(引擎優化)、易維護 | 難以覆蓋所有擴展區、無法統計分類 | 簡單驗證(如「必須含中文」)、高頻調用路徑 |
| 第三方庫 | 功能豐富(如 ICU4J、Apache Commons Lang) | 引入依賴、體積增大 | 複雜國際化處理、斷詞、轉寫等進階需求 |
Pattern.compile(".*[\\u4E00-\\u9FA5].*")Character.codePointAt 處理增補字符(> U+FFFF)str.chars().parallel().mapToObj(c -> (char)c)...