Статьи

Путаница длины строки Java

Факты и терминология

Как вы, наверное, знаете, Java использует UTF-16 для представления строк . Чтобы понять путаницу с String.length () , вы должны быть знакомы с некоторыми терминами Encoding / Unicode.

Кодовая точка: уникальное целочисленное значение, представляющее символ в кодовом пространстве.

Кодовая единица: битовая последовательность, используемая для кодирования символов (кодовые точки). Для представления кодовой точки может потребоваться одна или несколько единиц кода.

UTF-16

Кодовые точки Unicode логически разделены на 17 плоскостей. Первая плоскость, Базовая многоязычная плоскость (BMP), содержит «классические» символы (от U + 0000 до U + FFFF). Другие плоскости содержат дополнительные символы (от U + 10000 до U + 10FFFF).

Символы (кодовые точки) из первой плоскости кодируются в одну 16-битную кодовую единицу с одинаковым значением. Дополнительные символы (кодовые точки) кодируются в двух кодовых единицах (для конкретных кодировок, пояснение см. В Wiki ).

пример

Символ:
кодовая точка Unicode: U + 0041
UTF-16 кодовых единиц: 0041

Символ: Математическая двойная
буква A Кодовая точка Unicode: U + 1D538 Кодовые единицы
UTF-16: D835 DD38

Как вы можете видеть здесь, есть символы, которые закодированы в двух единицах кода.

String.length ()

Давайте посмотрим на Javadoc метода length () :

public int length()
Returns the length of this string. The length is equal to the number of Unicode code units in the string.

Поэтому, если у вас есть один дополнительный символ, который состоит из двух кодовых единиц, длина этого одного символа равна двум .

// Mathematical double-struck capital A
String str = "\uD835\uDD38";
System.out.println(str);
System.out.println(str.length()); //prints 2

Что правильно в соответствии с документацией, но, возможно, это не ожидается.

~ Решение

Вам нужно посчитать кодовые точки, а не кодовые единицы:

String str = "\uD835\uDD38";
System.out.println(str);
System.out.println(str.codePointCount(0, str.length()));

Смотрите:  codePointCount (int beginIndex, int endIndex)

Ссылки / источники