Калькулятор длины строки

Вставьте строку, и инструмент сообщит ее длину в четырех разных смыслах, .length в стиле JavaScript (кодовые единицы UTF-16), кодовые точки Unicode, кластеры графем (то, что пользователь воспринимает как один символ) и байты UTF-8 (то, что на самом деле хранит столбец вашей базы данных). Эти числа расходятся для любой строки с эмодзи, флагами или комбинируемыми знаками, и это расхождение является источником множества багов.

Четыре смысла длины строки

  1. 1

    Кодовые единицы UTF-16

    То, что возвращает `str.length` в JavaScript. 1 для большинства символов, 2 для любой кодовой точки за пределами U+FFFF (эмодзи, древние письменности).

  2. 2

    Кодовые точки

    По одной на каждый скаляр Unicode. Эмодзи: по 1 каждый; последовательности ZWJ: несколько.

  3. 3

    Кластеры графем

    То, что пользователь называет «одним символом». `🇺🇸`: это 2 кодовые точки, но 1 графема. `n̈`: это 2 кодовые точки, но 1 графема.

  4. 4

    Байты UTF-8

    То, что хранит ваша БД. ASCII = 1 байт каждый; распространенные европейские = 2; CJK = 3; большинство эмодзи = 4.

Примеры

Строка JS .length Кодовые точки Графемы Байты UTF-8
hello 5 5 5 5
café 4 4 4 5
😀 2 1 1 4
🇺🇸 4 2 1 8
👨‍👩‍👧 (семья) 8 5 1 18
n̈ (n + диерезис) 2 2 1 3

Почему числа различаются

Строки JavaScript, это UTF-16, поэтому кодовая точка выше U+FFFF хранится как суррогатная пара, две кодовые единицы UTF-16. "😀".length === 2. Пользователи это ненавидят, потому что воспринимают 😀 как один символ.

Графемы идут дальше: флаг страны, это две кодовые точки региональных индикаторов, которые пользователь видит как один флаг. "🇺🇸".length === 4 в JavaScript, что кажется абсурдом, но так оно и есть. Чтобы перебирать графемы, используйте Intl.Segmenter (современный), библиотеку grapheme-splitter или обрабатывайте вручную.

Байты UTF-8: что хранит ваша база данных

Для столбца типа VARCHAR(255):

  • В MySQL utf8 (фактически: utf8mb3) 255, это байты. café занимает 5 байтов, так что помещается 51 копия.
  • В MySQL utf8mb4 (настоящий UTF-8, включая эмодзи) это по-прежнему байты, но кодировка поддерживает 4-байтовые последовательности.
  • В Postgres VARCHAR(255) 255, это символы (кодовые точки), а не байты.
  • В SQL Server VARCHAR зависит от collation; NVARCHAR считает 2-байтовые единицы UCS-2.

Если вы задаете размер полей БД по видимому пользователю лимиту символов, используйте байты × 4 для запаса в столбцах UTF-8, каждая графема потенциально занимает до 4 байтов на кодовую точку, а последовательности ZWJ добавляют еще.

Подсчет символов в стиле Twitter

Twitter считает твит по особому правилу: кодовые точки, но эмодзи и идеограммы CJK считаются за 2. Твит на 100% из ASCII может быть 280 символов; твит со 140 эмодзи достигает максимума на 140 «символах».

Подсчет SMS: 160 символов в 7-битном GSM. Любой не-GSM символ (á, é, ñ, эмодзи) переключает кодировку на UCS-2, и длина вашего сообщения падает до 70 символов.

Практическое применение

  • Подбор размера столбцов БД, проверьте количество байтов перед написанием миграции.
  • Контроль квоты API, большинство API считают байты, а не символы.
  • Валидация форм, показывайте пользователю точный подсчет символов, соответствующий его ожиданиям (графемы).
  • Отладка производительности, почему этот regex итерирует медленно? Потому что ввод в 3 раза длиннее в кодовых единицах, чем в графемах.

Часто задаваемые вопросы

Этот эмодзи, последовательность ZWJ, объединяющая несколько кодовых точек (например, эмодзи семьи, это 7 кодовых точек). Twitter считает его за 2 символа по правилу веса Unicode; ваш редактор показывает 1 графему. Оба технически правы, просто они измеряют разное.

В базах UTF-8 закладывайте 4 байта на ожидаемый символ для запаса. Поле на 100 символов (графем) должно быть VARCHAR(400) байтов, или, если ваша БД считает в символах, как Postgres, VARCHAR(100) с настройкой charset.

В JavaScript зависит от формы композиции. NFC-композированный (U+00E1) имеет длину 1; NFD-декомпозированный (U+0061 + U+0301) имеет длину 2. Один и тот же видимый символ, разные последовательности байтов.

Эмодзи семей и профессий, это длинные последовательности ZWJ. Шрифты без полной поддержки отрисовывают каждую кодовую точку как отдельный глиф, поэтому 👨‍💻 превращается в 👨+💻. Обновление шрифта ОС это исправляет.

Сопутствующие инструменты

Генератор названий городов

Создавайте вымышленные названия городов, посёлков, деревень и столиц для миростроения, карт, игр, историй и тестовых данных с короткими заметками к каждому результату.

Переводчик иконок

Введите английский текст, и каждое слово из встроенного списка получит подходящий эмодзи. Скопируйте результат как текст с эмодзи.

Генератор бегущей строки

Создавайте анимированные бегущие заголовки с настраиваемой скоростью, размером шрифта и цветами. Предпросматривайте CSS-строку marquee или панель объявлений вживую в браузере.

Символы стрелок для копирования

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

Переводчик Эндермана

Превратите любую фразу в речь Эндермена в стиле Minecraft: растяните гласные и переверните каждое второе слово. Скопируйте результат в чат, на таблички или в посты фанатов.

Символ «меньше или равно»

Копируйте знак ≤ и связанные математические символы сравнения. Включает Unicode, HTML-сущности и разметку LaTeX для электронных таблиц, научных работ и веб-страниц.

Инструмент доступен на других языках