//utf8字符长度1-6,可以根据每个字符第一个字节判断整个字符长度:
//0xxxxxxx {0x00 ~ 0x7F ASCII 占1个字节}
//110xxxxx 10xxxxxx {0xC0 ~ 0xDF UTF-8 占2个字节}
//1110xxxx 10xxxxxx 10xxxxxx {0xE0 ~ 0xEF UTF-8 占3个字节}
//11110xxx 10xxxxxx 10xxxxxx 10xxxxxx {0xF0 ~ 0xF7 UTF-8 占4个字节}
//111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx {0xF8 ~ 0xFB UTF-8 占5个字节}
//1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx {0xFC ~ 0xFD UTF-8 占6个字节}
//如果一个字节,最高位(第 8 位)为 0,表示这是一个 ASCII 字符(00 - 7F)。可见,所有 ASCII 编码已经是 UTF-8 了。
//如果一个字节,以 11 开头,连续的 1 的个数暗示这个字符的字节数,例如:110xxxxx 代表它是双字节 UTF-8 字符的首字节。
//如果一个字节,以 10 开始,表示它不是首字节,需要向前查找才能得到当前字符的首字
伪代码:
if (byte <= 0x7F) then ASCII 占用1个字节
if (byte >= 0xC0 && byte <= 0xDF) then 首字节 UTF-8 占用2个字节
if (byte >= 0xE0 && byte <= 0xEF) then 首字节 UTF-8 占用3个字节
if (byte >= 0xF0 && byte <= 0xF7) then 首字节 UTF-8 占用4个字节
if (byte >= 0xF8 && byte <= 0xFB) then 首字节 UTF-8 占用5个字节
if (byte >= 0xFC && byte <= 0xFD) then 首字节 UTF-8 占用6个字节
if (byte > 0x7F && byte < 0xC0 ) then UTF-8非首字节
Java实现:
public int utf8StringLength(String text){
int length = 0;
if (text != null && text.length() >0){
byte[] byteArr = text.getBytes(StandardCharsets.UTF_8);
for (int i = 0; i < byteArr.length;){
byte byteData = byteArr[i];
//因为Java不支持无符号类型,这里将byte转为int数据
int data = Byte.toUnsignedInt(byteData);
//占用1个字节
if (data <= 0x7F){
i += 1;
}
//占用2个字节
if (data >= 0xC0 && data <= 0xDF){
i += 2;
}
//占用3个字节,中文一般为三个字节
if (data >= 0xE0 && data <= 0xEF){
i += 3;
}
//占用4个字节
if (data >= 0xF0 && data <= 0xF7){
i += 4;
}
//占用5个字节
if (data >= 0xF8 && data <= 0xFB){
i += 5;
}
//占用6个字节
if (data >= 0xFC && data <= 0xFD){
i += 6;
}
//UTF-8非首字节
if (data > 0x7F && data < 0xC0){
i += 1;
continue;
}
//长度+1
length += 1;
}
}
return length;
}