首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 判斷字串中英文字符:Unicode Block 精準識別與正則實戰

     編輯:Java 相關知識

核心需求與挑戰

判斷字串是否包含中文、英文、標點等字符類型,常見於輸入驗證、文本統計、敏感詞過濾等場景。單純用正則 [\u4e00-\u9fa5] 只覆蓋基本漢字區,無法識別擴展區、兼容區、標點符號等。本文提供基於 Character.UnicodeBlock 的完整解決方案。

Unicode Block 完整分類識別

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)...
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved