需求:
需要判断输入字符是否是一个汉字,因为汉字都有唯一的Unicode码点,因此使用Unicode 码点判断是否汉字,这里用四字节汉字作为一个案例进行演示,这个字在扩展B区,即"U+20000~U+2A6D6"
备注:这里的Unicode 编码 20164是十六进制编码,即判断 20164 是否是在“20000~2A6D6”之间,因为此字是四字节汉字,java在进行处理时会有一些问题,因为java在存储汉字时,使用UTF-16编码代码单元来存储汉字,如果码点值小于65535(十进制),则用一个代码单元存储,如果是大于65535 则使用两个代码单元存储。因此在循环时需要使用码点数进行遍历,而不能根据字符串长度。
1.字符串遍历
根据上面的需求,第一步需要完成字符串的遍历,将字符串中的每个汉字挨个进行遍历
字符串遍历(异常情况)代码解析:
import java.util.regex.Pattern;
import java.util.stream.IntStream;
/**
* @Description TODO
* @date 2024/10/28 9:47
* @Version 1.0
* @Author gezongyang
*/
public class TestCharset {
public static void main(String[] args) {
String testString = "我𠅤";
for (int i = 0; i < testString.length(); i++) {
int codePoint = testString.codePointAt(i);
System.out.println("Code point: " + Integer.toHexString(codePoint));
}
}
}
字符串遍历(正常情况)代码解析:
import java.util.regex.Pattern;
import java.util.stream.IntStream;
/**
* @Description TODO
* @date 2024/10/28 9:47
* @Version 1.0
* @Author gezongyang
*/
public class TestCharset {
public static void main(String[] args) {
String testString = "我𠅤";
int length = testString.length();
for (int i = 0; i < length; ) {
int codePoint = testString.codePointAt(i);
System.out.println("Code point: " + Integer.toHexString(codePoint) + ", Character: " + new String(Character.toChars(codePoint)));
//遍历索引位置偏移量为上个码点的索引值
i += Character.charCount(codePoint);
}
}
}
2.字符校验是否为汉字
说明:为了校验一个字符串中的每个字符是否都是汉字,包括那些码点值大于65536的生僻字(即增补平面中的汉字),需要遍历字符串中的每一个字符,判断每个字符的码点值是否在 汉字的Unicode区间内
* 扩展A区:\u3400-\u4DBF
* 扩展B区:\U00020000-\U0002A6DF
* 扩展C区:\U0002A700-\U0002B73F
* 扩展D区:\U0002B740-\U0002B81F
* 扩展E区:\U0002B820-\U0002CEAF
* 扩展F区:\U0002CEB0-\U0002EBEF
下面是示例代码:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.IntStream;
/**
* @Description TODO
* @date 2024/10/28 9:47
* @Version 1.0
* @Author gezongyang
*/
public class TestCharset {
public static boolean isChineseCharacter(int codePoint) {
// 常用汉字范围
if (codePoint >= 0x4e00 && codePoint <= 0x9fa5) {
return true;
}
// 扩展A
if (codePoint >= 0x3400 && codePoint <= 0x4dbf) {
return true;
}
// 扩展B
if (codePoint >= 0x20000 && codePoint <= 0x2a6df) {
return true;
}
// 扩展C
if (codePoint >= 0x2a700 && codePoint <= 0x2b73f) {
return true;
}
// 扩展D
if (codePoint >= 0x2b740 && codePoint <= 0x2b81f) {
return true;
}
// 扩展E
if (codePoint >= 0x2b820 && codePoint <= 0x2ceaf) {
return true;
}
// 扩展F
if (codePoint >= 0x2ceb0 && codePoint <= 0x2ebef) {
return true;
}
// 更多的扩展可以继续添加
return false;
}
public static void main(String[] args) {
String testString = "𠅤我";
// 遍历字符串中的每个字符
for (int i = 0; i < testString.length(); ) {
int codePoint = testString.codePointAt(i);
boolean chineseCharacter = isChineseCharacter(codePoint);
System.out.println(chineseCharacter);
// 更新索引以跳过当前字符
i += Character.charCount(codePoint);
}
}
}
校验结果:
true
true