Java 一个21字节的UTF-8序列怎么可能只有5个字符?

Java 一个21字节的UTF-8序列怎么可能只有5个字符?,java,unicode,encoding,utf-8,string-length,Java,Unicode,Encoding,Utf 8,String Length,在编写了一些基本代码来计算字符串中的字符数之后,我发现了一个例子,其中UTF-8编码输出从一个5“字符字符串创建了21个字节 以下是输出: 我知道Java对字符的内部表示是2个字节,有些字符可能需要两个Unicode代码单元来显示 由于UTF-8每个字符使用的字节数不超过4个,那么对于5个字符的字符串,长度如何可能超过20个 以下是消息来源: import java.io.UnsupportedEncodingException; public class StringTest {

在编写了一些基本代码来计算
字符串中的字符数之后,我发现了一个例子,其中UTF-8编码输出从一个5“字符
字符串创建了21个字节

以下是输出:

我知道Java对字符的内部表示是2个字节,有些字符可能需要两个Unicode代码单元来显示

由于UTF-8每个字符使用的字节数不超过4个,那么对于5个字符的
字符串
,长度如何可能超过20个

以下是消息来源:

import java.io.UnsupportedEncodingException;

public class StringTest {

    public static void main(String[] args) {
        displayStringInfo("อภิชาติ");
    }

    public static void displayStringInfo(String s) {
        System.out.println("Code units " + s.length());     
        try {
            System.out.println("UTF8 Bytes " + s.getBytes("UTF-8").length);
        } catch (UnsupportedEncodingException e) { // not handled }
        System.out.println("Characters " + characterLength(s));
    }

    public static int characterLength(String s) {
        int count = 0;
        for(int i=0; i<s.length(); i++) {
            if(!isLeadingUnit(s.charAt(i)) && !isMark(s.charAt(i))) count++;
        }
        return count;
    }

    private static boolean isMark(char ch) {
        int type = Character.getType(ch);
        return (type == Character.NON_SPACING_MARK ||
               type == Character.ENCLOSING_MARK ||
               type == Character.COMBINING_SPACING_MARK);
    }

    private static boolean isLeadingUnit(char ch) {
        return Character.isHighSurrogate(ch);
    }
}
import java.io.UnsupportedEncodingException;
公共类字符串测试{
公共静态void main(字符串[]args){
displayStringInfo(“อภิชาติ");
}
公共静态void displayStringInfo(字符串s){
System.out.println(“代码单位”+s.length());
试一试{
System.out.println(“UTF8字节”+s.getBytes(“UTF-8”)。长度);
}捕获(不支持DencodingException e){//未处理}
System.out.println(“字符”+字符长度);
}
公共静态int字符长度(字符串s){
整数计数=0;
对于(int i=0;i,您的“5个字符”字符串实际上由7个Unicode代码点组成:

  • U+0E2D泰文字符O ANG
  • U+0E20泰文字符PHO SAMPHAO
  • U+0E34泰国字符SARA I
  • U+0E0A泰文字符CHO CHANG
  • U+0E32泰国字符SARA AA
  • U+0E15泰语字符到TAO
  • U+0E34泰国字符SARA I

它们都在U+0800到U+FFFF范围内,UTF-8中每个字符需要3个字节,因此总长度为7×3=21个字节。

字符串中有7个字符:

 ' อ' (0x0e2d) encoded as {0xe0, 0xb8, 0xad}
  'ภ' (0x0e20) - / -      {0xe0, 0xb8, 0xa0}
  ' ิ' (0x0e34) - / -      {0xe0, 0xb8, 0xb4}
  'ช' (0x0e0a) - / -      {0xe0, 0xb8, 0x8a}
  'า' (0x0e32) - / -      {0xe0, 0xb8, 0xb2}
  'ต' (0x0e15) - / -      {0xe0, 0xb8, 0x95}
  ' ิ' (0x0e34) - / -      {0xe0, 0xb8, 0xb4}
每个符号由UTF-8中的三个字节编码,依此类推
当我编辑此
อภิชาติ在记事本中,
ภิ看起来像两个字符(同样适用于
ติ)是的,我假设它们都是合成字符,但其中两个似乎结合了一个变音符号“字符”“。是时候停止使用“字符”这个词了。它是代码点、字形还是什么。utf8everywhere.orgThank,有一刻我愚蠢地忘记了UTF-8在上限范围内可以使用比UTF-16更多的字节。当我的结果显示我有7个Unicode代码点时,这应该是显而易见的。
 ' อ' (0x0e2d) encoded as {0xe0, 0xb8, 0xad}
  'ภ' (0x0e20) - / -      {0xe0, 0xb8, 0xa0}
  ' ิ' (0x0e34) - / -      {0xe0, 0xb8, 0xb4}
  'ช' (0x0e0a) - / -      {0xe0, 0xb8, 0x8a}
  'า' (0x0e32) - / -      {0xe0, 0xb8, 0xb2}
  'ต' (0x0e15) - / -      {0xe0, 0xb8, 0x95}
  ' ิ' (0x0e34) - / -      {0xe0, 0xb8, 0xb4}