Unicode
Unicode中的CJK(和CJKV)指汉字,即在中文、日文、韩文和越南文中使用的汉字。对于Unicode脚本命名,它不是指象日语片假名和平假名或韩语谚文等音标书写的文字。汉字被称为统一的,这意味着每个表意字符只有一个Unicode代码点,无论用于哪种语言。
这意味着Unicode(反过来也是Android / Java)不能基于单个表意字符来确定语言。甚至简体/繁体中文字符也不能轻松区分编码。这与无法知道字符“a”属于英语、法语还是西班牙语的想法相同,需要更多上下文来确定。
但是,您可以使用Unicode编码来确定日文平假名/片假名和韩文谚文。这些字符的存在将是附近汉字属于同一语言的良好指示。
Android
您可以在某个索引处找到代码点。
int codepoint = Character.codePointAt(myString, offset)
如果您想要遍历字符串中的代码点:
final int length = myString.length();
for (int offset = 0; offset < length; ) {
final int codepoint = Character.codePointAt(myString, offset);
offset += Character.charCount(codepoint);
}
一旦您获得了代码点,您可以使用它来查找所在的代码块。
Character.UnicodeBlock block = Character.UnicodeBlock.of(codepoint)
然后,您可以使用代码块来测试表意文字或语言。
CJK
通过扫描Unicode代码块,我认为这些覆盖了所有CJK表意符号。如果我遗漏了任何内容,请随意编辑我的答案或留言。
private boolean isCJK(int codepoint) {
Character.UnicodeBlock block = Character.UnicodeBlock.of(codepoint);
return (
Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS.equals(block)||
Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A.equals(block) ||
Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B.equals(block) ||
Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C.equals(block) ||
Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D.equals(block) ||
Character.UnicodeBlock.CJK_COMPATIBILITY.equals(block) ||
Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS.equals(block) ||
Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS.equals(block) ||
Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT.equals(block) ||
Character.UnicodeBlock.CJK_RADICALS_SUPPLEMENT.equals(block) ||
Character.UnicodeBlock.CJK_STROKES.equals(block) ||
Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION.equals(block) ||
Character.UnicodeBlock.ENCLOSED_CJK_LETTERS_AND_MONTHS.equals(block) ||
Character.UnicodeBlock.ENCLOSED_IDEOGRAPHIC_SUPPLEMENT.equals(block) ||
Character.UnicodeBlock.KANGXI_RADICALS.equals(block) ||
Character.UnicodeBlock.IDEOGRAPHIC_DESCRIPTION_CHARACTERS.equals(block));
}
以下带有注释的部分(向右滚动)仅适用于API 19及以上版本。但是,如果您需要支持早期版本,则可以安全地删除这些内容,因为它们很少使用。此外,Unicode定义了CJK扩展E,但在本文撰写时,在Android / Java中不支持该扩展。如果您一定需要包含所有内容,则可以直接将代码点与Unicode块范围进行比较。
这个网站是浏览它们的便利之处。 您也可以在
Unicode 网站上查看它们。
如果您不需要支持API 19以下的版本,则
isIdeographic
使测试非常容易(尽管我不知道它是否返回与上面的方法完全相同的匹配)。
private boolean isCJK(int codepoint) {
return Character.isIdeographic(codepoint);
}
或者对于 API 24+,可以使用以下代码:
private boolean isCJK(int codepoint) {
return (Character.UnicodeScript.of(codepoint) == Character.UnicodeScript.HAN);
}
日语
如果要测试平假名或片假名,这个应该可以很好地工作:
private boolean isJapaneseKana(int codepoint) {
Character.UnicodeBlock block = Character.UnicodeBlock.of(codepoint);
return (
Character.UnicodeBlock.HIRAGANA.equals(block) ||
Character.UnicodeBlock.KATAKANA.equals(block) ||
Character.UnicodeBlock.KATAKANA_PHONETIC_EXTENSIONS.equals(block));
}
如果您支持API 24+,可以使用以下代码:
(这需要更多测试。请参见下面的评论。)
private boolean isJapaneseKana(int codepoint) {
return (Character.UnicodeScript.of(codepoint) == Character.UnicodeScript.HIRAGANA ||
Character.UnicodeScript.of(codepoint) == Character.UnicodeScript.KATAKANA);
}
韩语
为了在较低的API上测试韩文字母,您可以使用
private boolean isKoreanHangul(int codepoint) {
Character.UnicodeBlock block = Character.UnicodeBlock.of(codepoint);
return (Character.UnicodeBlock.HANGUL_JAMO.equals(block) ||
Character.UnicodeBlock.HANGUL_JAMO_EXTENDED_A.equals(block) || // api 19
Character.UnicodeBlock.HANGUL_JAMO_EXTENDED_B.equals(block) || // api 19
Character.UnicodeBlock.HANGUL_COMPATIBILITY_JAMO.equals(block) ||
Character.UnicodeBlock.HANGUL_SYLLABLES.equals(block));
}
如果需要的话,删除标记为API 19的行。
或者对于API 24+:
private boolean isKoreanHangul(int codepoint) {
return (Character.UnicodeScript.of(codepoint) == Character.UnicodeScript.HANGUL);
}
深入研究