一个21字节的UTF-8序列如何仅来自5个字符?

Mic*_*ael 3 java unicode encoding utf-8 string-length

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

这是输出:

String ==¦ ??????? ¦==
Code units 7
UTF8 Bytes 21
8859 Bytes 7
Characters 5
Run Code Online (Sandbox Code Playgroud)

我知道Java的内部表示char是2个字节,并且有些字符可能需要两个Unicode代码单元才能显示它们.

由于UTF-8每个字符不使用超过4个字节,对于5个字符,如何byte[]长度超过20个String

这是来源:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

dan*_*n04 9

您的"5个字符"字符串实际上由7个Unicode代码点组成:

  • U + 0E2D THAI CHARACTER O ANG
  • U + 0E20 THAI CHARACTER PHO SAMPHAO
  • U + 0E34 THAI CHARACTER SARA I
  • U + 0E0A THAI CHARACTER CHO CHANG
  • U + 0E32 THAI CHARACTER SARA AA
  • U + 0E15泰国人物
  • U + 0E34 THAI CHARACTER SARA I

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