如何判断一个字符是否为汉字?

给定一个字符串,判断这个字符串每个位置的字符是否为汉字。

Unicode编码

问题就是这个字符可以是中文,日文,英文,韩文,藏文等等全世界所有的语言文字和符号。这么多语言文字和符号就算是人类也不能一眼就能认出来。常见的文字符号我们还是能认出来的,中文日文韩文英文完全没问题,但是如果来个意大利文俄文德文混在一起,对于我们一般人就未必能看出来了。

那计算机系统如何解决这个问题的呢?

其实非常简单:就是通过编码来实现的,简单的说就是给每个符号设定一个编号,每个文字符号都有唯一一个编号(号码),然后将每个文字符号的语言属性与这个编号(号码)关联起来。以后根据这个号码就可以知道这个文字是哪个语言的符号。收集所有的符号并整理出一套号码的过程就是编码的过程。

根据收集的数量和编号方式的不同就有了不同的编码方式。而目前最全的而且还预留号码给未来可能出现新符号的编码方式就是“万国码”,又叫统一码,或者叫“单一码”,英文叫Unicode。成为了计算机的一项业界标准。

那这个Unicode有多少码位呢?(即可以标识多少个字符?)

答:可以有17组(0x0000-0xFFFF)个码位,每组成为一个平面(Plane),即17*(16*16*16*16)=17*65536=111,4112个。也就是说最多可以标识一百多万个符号。实际情况是还没有这么多符号,所有很多码号都是预留给后来新符号扩展用的。

这个unicode编码集最终在计算机内又以UTF8,UTF16,UTF32等编码方式来表示对应的码号。具体这些UTF编码方式可以再开几个话题。

回到问题本身:

首先,对于计算机而言,每个字符都是以某种编码的方式显示给人类阅读的。同样人类需要把可读的文字转化为计算机可读的方式显示给它。需要先讲字符转化为对应的计算机认识的表示字(char)。简单的说就是每个文本都有对应的编码属性。

其次,当字符被按其编码转化为char类型后,可以根据其在对应编码中的位置来判断其属于哪类文字。

最后,有很多编码。常用的编码有unicode。(UTF8, UTF16), 还有汉字编码GBK,GB2312等等。

这里列出Unicode编码以供参考:

      (1)0000~007Fh:基本拉丁字母区。其中0000~001Fh为C0控
         制码,0020h为空格(space),0021~007Eh为ASCII图形
         字符,007Fh为句柄DEL。事实上,这128个字符码只要
         把前8个位去掉就可变成习见的8位形式的ASCII码。

      (2)0080~00A0h:句柄区。其中0080~009Fh为C1句柄,
         00A0h为不中断空格(no-break space)。

      (3)00A1~1FFFh:拼音文字区。收容除基本拉丁字母以外的各种
         拼音文字字符,包括欧洲各国语言、希腊文、斯拉夫语文、
         希伯来文、阿拉伯文、亚美尼亚文、印度各地方言、马来文、
         泰文、寮文、柬普寨文、满文、蒙文、藏文、印地安语文等。

      (4)2000~28FFh:符号区。收容各种符号,包括标点符号、上下
         标、钱币符号、数字、箭头、数学符号、工程符号、光学辨
         识符号、带圈或带括符的文数字、表格绘制符号、地理图标、
         盲用点字、装饰图形等。

      (5)2E80~33FFh:中日韩符号区。收容康熙字典部首、中日韩辅
         助部首、注音符号、日本假名、韩文音符,中日韩的符号、
         标点、带圈或带括符文数字、月份,以及日本的假名组合、
         单位、年号、月份、日期、时间等。

      (6)3400~4DFFh:中日韩认同表意文字扩充A区,总计收容6,582
         个中日韩汉字。

      (7)4E00~9FFFh:中日韩认同表意文字区,总计收容20,902个中
         日韩汉字。

中日韩越语言字符区块:

Block                                   Range       Comment
--------------------------------------- ----------- ----------------------------------------------------
CJK Unified Ideographs                  4E00-9FFF   Common
CJK Unified Ideographs Extension A      3400-4DBF   Rare
CJK Unified Ideographs Extension B      20000-2A6DF Rare, historic
CJK Unified Ideographs Extension C      2A700–2B73F Rare, historic
CJK Unified Ideographs Extension D      2B740–2B81F Uncommon, some in current use
CJK Unified Ideographs Extension E      2B820–2CEAF Rare, historic
CJK Compatibility Ideographs            F900-FAFF   Duplicates, unifiable variants, corporate characters
CJK Compatibility Ideographs Supplement 2F800-2FA1F Unifiable variants
CJK Symbols and Punctuation             3000-303F

最后,通过不同编程语言来判断是否是汉字。

Java

Now Character.isIdeographic(int codepoint) would tell wether the codepoint is a CJKV (Chinese, Japanese, Korean and Vietnamese) ideograph.

Nearer is using Character.UnicodeScript.HAN.

So:

System.out.println(containsHanScript("xxx已下架xxx"));

public static boolean containsHanScript(String s) {
    for (int i = 0; i < s.length(); ) {
        int codepoint = s.codePointAt(i);
        i += Character.charCount(codepoint);
        if (Character.UnicodeScript.of(codepoint) == Character.UnicodeScript.HAN) {
            return true;
        }
    }
    return false;
}
Or in java 8:

public static boolean containsHanScript(String s) {
    return s.codePoints().anyMatch(
            codepoint ->
            Character.UnicodeScript.of(codepoint) == Character.UnicodeScript.HAN);
}

Javascript:

function isChineseChar(aChar){
   return /[\u3400-\u4DBF\u4E00-\u9FFF]/.test(aChar);
}

注意(小功课):网上有多个版本,\u4E00-\u9FFF,还有\u4E00-\u9FA5, 还有\u4E00-\u9FBB.有什么区别?以哪个为准?

参考文档:

  • http://baike.baidu.com/link?url=Q-wcXRlFCbyykUSOeM39vqkAW9LtSX9Lbc97_ohYUxNT8ZyBkFGtfWLWrCuFG6pLdGm5cIt4SfhKrl4uJ_N8WK
  • http://baike.baidu.com/item/编码方式
  • http://stackoverflow.com/questions/40099273/how-to-use-regular-expression-to-validate-chinese-input
  • http://stackoverflow.com/questions/20396456/how-to-do-word-counts-for-a-mixture-of-english-and-chinese-in-javascript

发表评论