Calculadora de Comprimento de String

Cole uma string e a ferramenta informa seu comprimento em quatro sentidos diferentes, estilo JavaScript .length (unidades de código UTF-16), pontos de código Unicode, clusters de grafemas (o que os usuários percebem como um caractere) e bytes UTF-8 (o que sua coluna de banco de dados realmente armazena). Esses números discordam para qualquer string com emoji, bandeiras ou marcas combinatórias, e essa discordância é a fonte de muitos bugs.

Os quatro sentidos do comprimento da string

  1. 1

    Unidades de código UTF-16

    O que `str.length` retorna em JavaScript. 1 para a maioria dos caracteres, 2 para qualquer ponto de código além de U+FFFF (emoji, scripts antigos).

  2. 2

    Pontos de código

    Um por escalar Unicode. Emojis são 1 cada; sequências ZWJ são múltiplas.

  3. 3

    Clusters de grafemas

    O que um usuário chama de "um caractere". `🇺🇸` é 2 pontos de código, mas 1 grafema. `n̈` é 2 pontos de código, mas 1 grafema.

  4. 4

    Bytes UTF-8

    O que seu banco de dados armazena. ASCII = 1 byte cada; comum europeu = 2; CJK = 3; a maioria dos emojis = 4.

Exemplos

String JS .length Pontos de código Grafemas Bytes UTF-8
hello 5 5 5 5
café 4 4 4 5
😀 2 1 1 4
🇺🇸 4 2 1 8
👨‍👩‍👧 (família) 8 5 1 18
n̈ (n + diacrítico) 2 2 1 3

Por que os números diferem

Strings JavaScript são UTF-16, então um ponto de código acima de U+FFFF é armazenado como um par de substituição, duas unidades de código UTF-16. "😀".length === 2. Os usuários odeiam isso porque pensam em 😀 como um caractere.

Grafemas vão mais longe: uma bandeira de país é dois pontos de código de indicador regional que o usuário vê como uma bandeira. "🇺🇸".length === 4 em JavaScript, o que parece absurdo, mas é isso. Para iterar sobre grafemas, use Intl.Segmenter (moderno), biblioteca grapheme-splitter, ou trate manualmente.

Bytes UTF-8: o que seu banco de dados armazena

Para uma coluna tipada VARCHAR(255):

  • No MySQL utf8 (real: utf8mb3), os 255 são bytes. café ocupa 5 bytes, então você encaixa 51 cópias.
  • No MySQL utf8mb4 (UTF-8 real, inclui emoji), ainda são bytes, mas a codificação suporta sequências de 4 bytes.
  • No Postgres VARCHAR(255), os 255 são caracteres (pontos de código), não bytes.
  • No SQL Server VARCHAR, varia por collation; NVARCHAR conta 2 bytes de unidades UCS-2.

Se você dimensionar campos de banco de dados pelo limite de caracteres visíveis ao usuário, use bytes × 4 para segurança em colunas UTF-8, cada grafema pode ocupar até 4 bytes por ponto de código, com sequências ZWJ adicionando mais.

Contagem de caracteres estilo Twitter

O Twitter conta um tweet por uma regra personalizada: pontos de código, mas emojis e ideogramas CJK contam como 2. Um tweet 100% ASCII pode ter 280 caracteres; um tweet com 140 emojis atinge o máximo de 140 “caracteres”.

Contagem SMS: 160 caracteres em GSM 7-bit. Qualquer caractere não-GSM (á, é, ñ, emoji) muda a codificação para UCS-2, e o comprimento da sua mensagem cai para 70 caracteres.

Usos práticos

  • Dimensionamento de coluna de banco de dados, verifique a contagem de bytes antes de escrever uma migração.
  • Aplicação de cota de API, a maioria das APIs conta bytes, não caracteres.
  • Validação de formulário, mostre ao usuário uma contagem precisa de caracteres que corresponda à sua expectativa (grafemas).
  • Depuração de desempenho, por que essa regex itera lentamente? Porque a entrada é 3x mais longa em unidades de código do que em grafemas.

Perguntas frequentes

Esse emoji é uma sequência ZWJ combinando múltiplos pontos de código (por exemplo, um emoji de família tem 7 pontos de código). O Twitter conta como 2 caracteres por regra de peso Unicode; seu editor mostra 1 grafema. Ambos estão tecnicamente certos, eles apenas medem coisas diferentes.

Em bancos de dados UTF-8, permita 4 bytes por caractere esperado para segurança. Um campo de 100 caracteres (grafema) deve ser VARCHAR(400) bytes, ou se seu banco de dados conta em caracteres como o Postgres, VARCHAR(100) com o tratamento de charset.

Em JavaScript: depende da forma de composição. Composto NFC (U+00E1) tem comprimento 1; decomposto NFD (U+0061 + U+0301) tem comprimento 2. Mesmo caractere visível, sequências de bytes diferentes.

Emojis de família e profissão são longas sequências ZWJ. Fontes sem suporte completo renderizam cada ponto de código como um glifo separado, então 👨‍💻 se torna 👨+💻. Atualizar a fonte do sistema operacional resolve isso.

Ferramentas relacionadas

Ferramenta disponível em outros idiomas