處理中英混雜字串時,常需區分中英文字元(如計算顯示寬度、截斷、排版)。本文提供基於位元運算的高效判斷實作。
Java char 為 UTF-16 編碼單元(2 bytes)。基本多文種平面(BMP)字元:
判斷邏輯:(ch & 0xFF80) != 0 或 ch > 0x7F 即可快速識別非 ASCII 字元(含中文)。
public class EnCnTest {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("請提供字串參數");
return;
}
String input = args[0];
byte[] bytes = input.getBytes(StandardCharsets.UTF_8); // 或預設編碼
boolean halfChinese = false;
for (int i = 0; i < bytes.length; i++) {
if (halfChinese) {
// 組合雙位元組字元(簡易示範,實際需依編碼處理)
byte[] ch = {bytes[i-1], bytes[i]};
String chStr = new String(ch, StandardCharsets.UTF_8);
System.out.println("索引 " + (i-1) + " 為中文: " + chStr);
halfChinese = false;
continue;
}
if ((bytes[i] & 0x80) == 0) {
// ASCII 字元
System.out.println("索引 " + i + " 為英文: " + (char)bytes[i]);
} else {
// 非 ASCII 首位元組(UTF-8 多位元組序列開頭)
halfChinese = true;
}
}
}
}
public class CharTypeUtils {
/** 判斷是否為中文字元(CJK 統一表意文字基本區) */
public static boolean isChinese(char ch) {
return ch >= 0x4E00 && ch <= 0x9FFF;
}
/** 判斷是否為 ASCII 字元 */
public static boolean isAscii(char ch) {
return ch <= 0x7F;
}
/** 計算字串顯示寬度(中文=2,英文=1) */
public static int displayWidth(String str) {
int width = 0;
for (char ch : str.toCharArray()) {
width += isChinese(ch) ? 2 : 1;
}
return width;
}
/** 依顯示寬度截取字串 */
public static String substringByWidth(String str, int maxWidth) {
int width = 0;
int end = 0;
for (char ch : str.toCharArray()) {
width += isChinese(ch) ? 2 : 1;
if (width > maxWidth) break;
end++;
}
return str.substring(0, end) + (end < str.length() ? "..." : "");
}
}
| 場景 | 錯誤做法 | 正確做法 |
|---|---|---|
| 位元組層面判斷 | 直接用 getBytes() 不指定編碼 | 明確指定 StandardCharsets.UTF_8 或系統編碼 |
| 補助平面字元 | 假設所有字元皆為 char | 使用 codePointAt / Character API 處理 Emoji、罕用字 |
| 全角英文/數字 | 視為中文寬度 | 依業務需求區分:ch >= 0xFF01 && ch <= 0xFF5E |
| 效能敏感場景 | 逐字元 Character.getType() | 位元運算或查表法(預計算查找表) |
位元運算法(ch > 0x7F)最簡潔高效,適合 ASCII 與非 ASCII 二分場景。精準識別中文需碼點區間判斷(0x4E00~0x9FFF)。實務中建議封裝為工具類,統一處理編碼、補助平面、全角字元等邊界情況。