Quantos caracteres podem ser codificados em UTF-8?

97

Se UTF-8 tiver 8 bits, isso não significa que pode haver no máximo 256 caracteres diferentes?

Os primeiros 128 pontos de código são iguais aos do ASCII. Mas diz que UTF-8 pode suportar até milhões de caracteres?

Como é que isso funciona?

eMRe
fonte
2
se você pudesse reavaliar esta questão porque todas as respostas estão erradas. Leia minha resposta: stackoverflow.com/a/45042566/124486
Evan Carroll
Nas codificações UTF-8, UTF-16, UTF-32 de Unicode, o número é o número de bits em suas unidades de código , um ou mais dos quais codificam um ponto de código Unicode.
Tom Blodget
1
Eu respondi a esta pergunta há um tempo na tentativa de endireitá-la: seria ótimo se você pesasse em relação à resposta escolhida, que é literalmente apenas uma citação da Wikipedia que não conta toda a história (espero que seja minha atualização é muito mais claro)
Evan Carroll

Respostas:

135

UTF-8 não usa um byte o tempo todo, é de 1 a 4 bytes.

Os primeiros 128 caracteres (US-ASCII) precisam de um byte.

Os próximos 1.920 caracteres precisam de dois bytes para codificar. Isso cobre o restante de quase todos os alfabetos latinos e também os alfabetos grego, cirílico, copta, armênio, hebraico, árabe, siríaco e tana, bem como as marcas diacríticas combinadas.

Três bytes são necessários para os caracteres no restante do plano multilíngue básico, que contém virtualmente todos os caracteres de uso comum [12], incluindo a maioria dos caracteres chineses, japoneses e coreanos [CJK].

Quatro bytes são necessários para caracteres em outros planos de Unicode, que incluem caracteres CJK menos comuns, vários scripts históricos, símbolos matemáticos e emoji (símbolos pictográficos).

fonte: Wikipedia

zwippie
fonte
oi @zwippie, eu sou novo nisso. Há algo que eu não entendo.! BMP usa 2 bytes que você diz que é 3? estou errado?
chiperortiz
1
@chiperortiz, o BMP é de fato 16 bits, portanto, pode ser codificado como UTF-16 com comprimento constante por caractere (UTF-16 também suporta ir além de 16 bits, mas é uma prática difícil e muitas implementações não o suportam). No entanto, para UTF-8, você também precisa codificar quanto tempo ele terá, então você perde alguns bits. É por isso que você precisa de 3 bytes para codificar o BMP completo. Isso pode parecer um desperdício, mas lembre-se de que o UTF-16 sempre usa 2 bytes, mas o UTF-8 usa um byte por caractere para a maioria dos caracteres latinos. Tornando-o duas vezes mais compacto.
sanderd17
O principal objetivo da pergunta do OP está relacionado a por que ele é chamado de UTF- 8 - isso não responde realmente a isso.
jbyrd
39

UTF-8 usa 1-4 bytes por caractere: um byte para caracteres ascii (os primeiros 128 valores Unicode são iguais a ascii). Mas isso requer apenas 7 bits. Se o bit mais alto ("sinal") for definido, isso indica o início de uma seqüência de bytes múltiplos; o número de bits altos consecutivos definido indica o número de bytes, então um 0, e os bits restantes contribuem para o valor. Para os outros bytes, os dois bits mais altos serão 1 e 0 e os 6 bits restantes serão para o valor.

Portanto, uma sequência de quatro bytes começaria com 11110 ... (e ... = três bits para o valor) e, em seguida, três bytes com 6 bits cada para o valor, resultando em um valor de 21 bits. 2 ^ 21 excede o número de caracteres Unicode, portanto, todos os Unicode podem ser expressos em UTF8.

CodeClown42
fonte
@NickL. Não, quero dizer 3 bytes. Nesse exemplo, se o primeiro byte de uma sequência multibyte começa em 1111, o primeiro 1 indica que é o início de uma sequência multibyte, então o número de 1's consecutivos indica o número de bytes adicionais na sequência (então um primeiro byte começará 110, 1110 ou 11110).
CodeClown42
Prova encontrada por suas palavras em RFC 3629. tools.ietf.org/html/rfc3629#section-3 . No entanto, não entendo por que preciso colocar "10" no início do segundo byte 110xxxxx 10xxxxxx? Por que não apenas 110xxxxx xxxxxxxx?
Kolobok
3
Resposta encontrada em softwareengineering.stackexchange.com/questions/262227/… . Apenas por razões de segurança (no caso de um único byte no meio do fluxo estar corrompido)
kolobok
@kolobok Ah. Sem segurança, você poderia codificar um valor de 21 bits em 3 bytes (3 bits indicando o comprimento, mais 21 bits). : D Provavelmente isso não é tão significativo, pelo menos em idiomas ocidentais WRT.
CodeClown42
Estou supondo que NickL perguntou isso, mas o que aconteceu com o resto dos bits naquele primeiro byte se o ... representa bytes subsequentes em vez de bits?
c6754
26

De acordo com esta tabela, * UTF-8 deve suportar:

2 31 = 2.147.483.648 caracteres

No entanto, a RFC 3629 restringiu os valores possíveis, então agora estamos limitados a 4 bytes , o que nos dá

2 21 = 2.097.152 caracteres

Observe que uma boa parte desses caracteres são "reservados" para uso personalizado, o que é realmente muito útil para fontes de ícones.

* A Wikipedia usada mostra uma tabela com 6 bytes - desde então eles atualizaram o artigo.

11/07/2017: corrigido para contagem dupla do mesmo ponto de código codificado com bytes múltiplos

mpen
fonte
Essa resposta é a contagem dupla do número de codificações possíveis. Depois de contar todos os 2 ^ 7, você não pode contá-los novamente em 2 ^ 11, 2 ^ 16, etc. O número correto de codificações possíveis é 2 ^ 21 (embora nem todos estejam sendo usados ​​atualmente).
Jimmy
@Jimmy Tem certeza que estou contando em dobro? 0xxxxxxxdá 7 bits utilizáveis, 110xxxxx 10xxxxxxdá mais 11 - não há sobreposição. O primeiro byte começa com 0no primeiro caso e 1no segundo caso.
MPEN
@mpen então qual ponto de código 00000001armazena e o que 11000000 100000001armazena?
Evan Carroll
1
@EvanCarroll Uhh .... ponto tomado. Não sabia que havia várias maneiras de codificar o mesmo ponto de código.
maio
1
Eu fui em frente e tentei responder isso sozinho, veja se você acha que esta é uma explicação melhor e responda à pergunta: stackoverflow.com/a/45042566/124486
Evan Carroll
21

Unicode vs UTF-8

Unicode resolve pontos de código em caracteres. UTF-8 é um mecanismo de armazenamento para Unicode. Unicode tem uma especificação. UTF-8 tem uma especificação. Ambos têm limites diferentes. UTF-8 tem um limite ascendente diferente.

Unicode

Unicode é designado com "planos". Cada avião carrega 2 16 pontos de código. Existem 17 planos em Unicode. Para um total de 17 * 2^16pontos de código. O primeiro plano, plano 0 ou BMP , é especial no peso do que carrega.

Em vez de explicar todas as nuances, deixe-me apenas citar o artigo acima sobre aviões.

Os 17 aviões podem acomodar 1.114.112 pontos de código. Destes, 2.048 são substitutos, 66 são não-personagens e 137.468 são reservados para uso privado, deixando 974.530 para atribuição pública.

UTF-8

Agora vamos voltar ao artigo com link acima,

O esquema de codificação usado por UTF-8 foi concebido com um limite muito maior de 2 31 pontos de código (32.768 planos), e pode codificar 2 21 pontos de código (32 aviões) mesmo se limitado a 4 bytes. [3] Como o Unicode limita os pontos de código aos 17 planos que podem ser codificados por UTF-16, os pontos de código acima de 0x10FFFF são inválidos em UTF-8 e UTF-32.

Então, você pode ver que pode colocar coisas em UTF-8 que não são Unicode válidas. Por quê? Porque UTF-8 acomoda pontos de código que o Unicode nem mesmo suporta.

UTF-8, mesmo com uma limitação de quatro bytes, suporta 2 21 pontos de código, o que é muito mais do que17 * 2^16

Evan Carroll
fonte
18

2.164.864 “caracteres” podem ser potencialmente codificados por UTF-8.

Este número é 2 ^ 7 + 2 ^ 11 + 2 ^ 16 + 2 ^ 21, que vem da maneira como a codificação funciona:

  • 0xxxxxxxCaracteres de 1 byte têm 7 bits para codificação (0x00-0x7F)

  • Os caracteres de 2 bytes têm 11 bits para codificação 110xxxxx 10xxxxxx(0xC0-0xDF para o primeiro byte; 0x80-0xBF para o segundo)

  • Os caracteres de 3 bytes têm 16 bits para codificação 1110xxxx 10xxxxxx 10xxxxxx(0xE0-0xEF para o primeiro byte; 0x80-0xBF para bytes de continuação)

  • Os caracteres de 4 bytes têm 21 bits para codificação 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(0xF0-0xF7 para o primeiro byte; 0x80-0xBF para bytes de continuação)

Como você pode ver, isso é significativamente maior do que o Unicode atual (1.112.064 caracteres).

ATUALIZAR

Meu cálculo inicial está errado porque não considera regras adicionais. Veja comentários a esta resposta para mais detalhes.

Ruben Reyes
fonte
2
Sua matemática não respeita a regra UTF-8 de que apenas a sequência de unidade de código mais curta tem permissão para codificar um ponto de código. Portanto, 00000001 é válido para U + 0001, mas 11110000 10000000 10000000 10000001 não é. Ref: Tabela 3-7. Seqüências de bytes UTF-8 bem formadas . Além disso, a questão é respondida diretamente pela tabela: basta somar os intervalos. (Eles são separados para excluir substitutos para UTF-16).
Tom Blodget
Tom - obrigado pelo seu comentário! Eu não estava ciente dessas restrições. Eu vi a tabela 3-7 e executei os números e parece que há 1.083.392 possíveis sequências válidas.
Ruben Reyes
6

UTF-8 é uma codificação de comprimento variável com um mínimo de 8 bits por caractere.
Os caracteres com pontos de código mais altos levarão até 32 bits.

deceze
fonte
2
Isso é enganoso. O ponto de código mais longo que você pode ter é 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx, portanto, apenas 21 bits podem ser usados ​​para codificar o caractere real.
Boris
5
Eu disse que os pontos de código podem levar até 32 bits para serem codificados, nunca afirmei que (por indução) você pode codificar 2 ^ 32 caracteres em UTF-8 de 32 bits. Mas isso é bastante discutível, já que você pode codificar todos os caracteres Unicode existentes em UTF-8, e você pode codificar ainda mais se esticar UTF-8 para 48 bits (que existe, mas está obsoleto), então não tenho certeza do que ponto enganoso é.
deceze
2

Verifique o Padrão Unicode e as informações relacionadas, como sua entrada de FAQ, UTF-8 UTF-16, UTF-32 e BOM . Não é tão fácil, mas é uma informação confiável, e muito do que você pode ler sobre o UTF-8 em outro lugar é questionável.

O “8” em “UTF-8” refere-se ao comprimento das unidades de código em bits. Unidades de código são entidades usadas para codificar caracteres, não necessariamente como um mapeamento um-para-um simples. UTF-8 usa um número variável de unidades de código para codificar um caractere.

A coleção de caracteres que podem ser codificados em UTF-8 é exatamente a mesma que em UTF-16 ou UTF-32, ou seja, todos os caracteres Unicode. Todos eles codificam todo o espaço de codificação Unicode, que inclui até mesmo não caracteres e pontos de código não atribuídos.

Jukka K. Korpela
fonte
1

Embora eu concorde com o mpen sobre os códigos UTF-8 máximos atuais (2.164.864) (listados abaixo, eu não poderia comentar sobre o dele), ele está errado por 2 níveis se você remover as 2 principais restrições do UTF-8: apenas 4 bytes limite e os códigos 254 e 255 não podem ser usados ​​(ele apenas removeu o limite de 4 bytes).

O código inicial 254 segue o arranjo básico dos bits iniciais (sinalizador de vários bits definido como 1, uma contagem de 6 1's e terminal 0, sem bits sobressalentes), dando a você 6 bytes adicionais para trabalhar (6 grupos 10xxxxxx, 2 adicionais ^ 36 códigos).

O código inicial 255 não segue exatamente a configuração básica, nenhum terminal 0, mas todos os bits são usados, dando a você 7 bytes adicionais (sinalizador de vários bits definido como 1, uma contagem de 7 1's e nenhum terminal 0 porque todos os bits são usados ; 7 grupos 10xxxxxx, mais 2 ^ 42 códigos).

Adicioná-los dá um conjunto final máximo de caracteres apresentáveis ​​de 4.468.982.745.216. Isso é mais do que todos os caracteres em uso atual, línguas antigas ou mortas e quaisquer línguas perdidas. Alguém com script angelical ou celestial?

Além disso, existem códigos de byte único que são negligenciados / ignorados no padrão UTF-8, além de 254 e 255: 128-191 e alguns outros. Alguns são usados ​​localmente pelo teclado, o código de exemplo 128 é geralmente um backspace de exclusão. Os outros códigos iniciais (e intervalos associados) são inválidos por um ou mais motivos ( https://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences ).

James V. Fields
fonte
0

O Unicode é casado com o UTF-8. O Unicode oferece suporte especificamente para 2 ^ 21 pontos de código (2.097.152 caracteres), que é exatamente o mesmo número de pontos de código compatível com UTF-8. Ambos os sistemas reservam o mesmo espaço 'morto' e zonas restritas para pontos de código, etc. ... em junho de 2018, a versão mais recente, Unicode 11.0, contém um repertório de 137.439 caracteres

Do padrão Unicode. Unicode FAQ

O padrão Unicode codifica caracteres no intervalo U + 0000..U + 10FFFF, o que equivale a um espaço de código de 21 bits.

Da página UTF-8 da Wikipedia. Descrição UTF-8

Desde a restrição do espaço de código Unicode para valores de 21 bits em 2003, UTF-8 é definido para codificar pontos de código em um a quatro bytes, ...

Nome em Exibição
fonte
21 bits são arredondados. Unicode suporta 1.114.112 pontos de código (U + 0000 a U + 10FFFF) como ele diz. (Às vezes descrito como 17 aviões de 65536.)
Tom Blodget
@TomBlodget, você está correto. a conclusão mais relevante dessa discussão é que o UTF-8 pode codificar todos os pontos atualmente definidos no padrão Unicode e provavelmente será capaz por um bom tempo.
Nome de exibição