Quantos bytes leva um caractere Unicode?

239

Estou um pouco confuso sobre codificações. Até onde eu sei, os caracteres ASCII antigos usavam um byte por caractere. Quantos bytes um caractere Unicode requer?

Presumo que um caractere Unicode possa conter todos os caracteres possíveis de qualquer idioma - estou correto? Então, quantos bytes ele precisa por caractere?

E o que significa UTF-7, UTF-6, UTF-16 etc.? São versões diferentes do Unicode?

Eu li o artigo da Wikipedia sobre Unicode, mas é bastante difícil para mim. Estou ansioso para ver uma resposta simples.

nan
fonte
15
Desculpe, não há uma resposta simples. Acho a coisa toda um pouco confusa. O Unicode foi cobrado por usar dois bytes e ser capaz de representar todos os caracteres, mas acontece que dois bytes não foram suficientes.
Jonathan Madeira
12
"Resposta simples": um caractere unicode leva de 1 a 4 bytes. O Unicode cobre muitos idiomas, mas não todos. A última vez que olhei, por exemplo, o Klingon não era um conjunto de caracteres Unicode oficial.
Peter G.
9
O Klingon não faz parte do próprio padrão Unicode, não. Ele usa a Área de uso privado do Uniode (U + F8D0 - U + F8FF).
Remy Lebeau
1
Pergunta do Salvador - obrigado. Minha situação é armazenar dados por meio de LMSs compatíveis com SCORM 1.2 ... o padrão para 'cmi.suspend_data' do SCORM 1.2 é 4096 bytes de dados que um desenvolvedor anterior assumiu que significava que poderíamos armazenar 4096 caracteres. Ah, cara, ele estava errado - acabei de descobrir por que nossos favoritos falham em cursos longos. Então agora eu sei que, como estamos usando UTF-8, são necessários 4 bytes por caractere, fornecendo 1024 caracteres.
danjah

Respostas:

147

Você não verá uma resposta simples porque não há uma.

Primeiro, o Unicode não contém "todos os caracteres de todos os idiomas", embora com certeza tente.

O próprio Unicode é um mapeamento, define pontos de código e um ponto de código é um número, geralmente associado a um caractere. Eu digo geralmente porque existem conceitos como combinar personagens. Você pode estar familiarizado com coisas como sotaques ou trema. Esses podem ser usados ​​com outro caractere, como um aou a, upara criar um novo caracter lógico. Um caractere, portanto, pode consistir em 1 ou mais pontos de código.

Para ser útil em sistemas de computação, precisamos escolher uma representação para essas informações. Essas são as várias codificações unicode, como utf-8, utf-16le, utf-32 etc. Elas se distinguem principalmente pelo tamanho de suas unidades de código. UTF-32 é a codificação mais simples, possui uma unidade de código de 32 bits, o que significa que um ponto de código individual se encaixa confortavelmente em uma unidade de código. As outras codificações terão situações em que um ponto de código precisará de várias unidades de código, ou esse ponto de código específico não poderá ser representado na codificação (este é um problema, por exemplo, com o UCS-2).

Devido à flexibilidade de combinar caracteres, mesmo dentro de uma determinada codificação, o número de bytes por caractere pode variar dependendo do caractere e da forma de normalização. Este é um protocolo para lidar com caracteres que possuem mais de uma representação (você pode dizer "an 'a' with an accent"quais são 2 pontos de código, um dos quais é um caractere de combinação ou "accented 'a'"qual é um ponto de código).

Logan Capaldo
fonte
1
ESTÁ BEM. Então, quantos bytes levam um determinado caractere representado em um determinado ponto de código? Por exemplo, o espaço sem quebra.
Nicolas Barbulesco 08/01
Os caracteres combinados tornam a vida de um programador um inferno quando se trata de escrever strlen (), substr () e outras funções de manipulação de strings em matrizes UTF8. Esse tipo de trabalho nunca será completo e sempre com erros.
Nulik 26/09/16
Eu escrevi uma demo que mostra o Windows-1252, UTF8 e UTF8-BOM codificado arquivos interpretados com cada codificação, e compara a igualdade entre os resultados: github.com/vladyrn/encodings_demo
Vlad
195

Estranhamente, ninguém apontou como calcular quantos bytes estão usando um caractere Unicode. Aqui está a regra para cadeias codificadas em UTF-8:

Binary    Hex          Comments
0xxxxxxx  0x00..0x7F   Only byte of a 1-byte character encoding
10xxxxxx  0x80..0xBF   Continuation byte: one of 1-3 bytes following the first
110xxxxx  0xC0..0xDF   First byte of a 2-byte character encoding
1110xxxx  0xE0..0xEF   First byte of a 3-byte character encoding
11110xxx  0xF0..0xF7   First byte of a 4-byte character encoding

Portanto, a resposta rápida é: são necessários 1 a 4 bytes, dependendo do primeiro, que indicará quantos bytes serão necessários.

paul.ago
fonte
8
Eu acredito que o valor hexadecimal máximo para um caractere de 4 bytes é 0xF7 (não 0xF4).
DJPJ
Muito obrigado! Eu estava apenas controlando o padrão IETF e não encontrei nada sobre codificação, e o artigo que estava lendo não entrava em detalhes suficientes para dizer quantos bits são usados ​​para representar o número de código à direita pontos por "personagem".
MarcusJ
1
Esta é agora na segunda página do meu "introdução de novos membros da equipe" cola, juntamente com as hilariantes primeiros dois comentários
Cee McSharpface
1
0xF4 não foi um erro, mas um esclarecimento. Os pontos de código Unicode estão no intervalo 0-0x10ffff, portanto, o último ponto de código é codificado como F4 8F BF BF.
Frediano Ziglio 02/12/19
38

Sei que esta pergunta é antiga e já tem uma resposta aceita, mas quero oferecer alguns exemplos (esperando que seja útil para alguém).

Até onde eu sei, os caracteres ASCII antigos usavam um byte por caractere.

Certo. Na verdade, como o ASCII é uma codificação de 7 bits, ele suporta 128 códigos (95 dos quais são imprimíveis); portanto, ele usa apenas meio byte (se isso faz algum sentido).

Quantos bytes um caractere Unicode requer?

Unicode apenas mapeia caracteres para pontos de código. Ele não define como codificá-los. Um arquivo de texto não contém caracteres Unicode, mas bytes / octetos que podem representar caracteres Unicode.

Presumo que um caractere Unicode possa conter todos os caracteres possíveis de qualquer idioma - estou correto?

Não. Mas quase. Então basicamente sim. Mas ainda não.

Então, quantos bytes ele precisa por caractere?

O mesmo que sua segunda pergunta.

E o que UTF-7, UTF-6, UTF-16 etc significam? São algumas versões Unicode?

Não, essas são codificações. Eles definem como bytes / octetos devem representar caracteres Unicode.

Alguns exemplos. Se alguns deles não puderem ser exibidos no seu navegador (provavelmente porque a fonte não os suporta), vá para http://codepoints.net/U+1F6AA(substitua 1F6AApelo código em hexadecimal) para ver uma imagem.

    • U + 0061 LETRA PEQUENA LATINA A: a
      • Nº: 97
      • UTF-8: 61
      • UTF-16: 00 61
    • SINAL DE DIREITOS AUTORAIS U + 00A9: ©
      • Nº: 169
      • UTF-8: C2 A9
      • UTF-16: 00 A9
    • SINAL REGISTRADO U + 00AE: ®
      • Nº: 174
      • UTF-8: C2 AE
      • UTF-16: 00 AE
    • U + 1337 PHWA SELÁVEL ETÍPICO:
      • Nº: 4919
      • UTF-8: E1 8C B7
      • UTF-16: 13 37
    • U + 2014 EM DASH:
      • Nº: 8212
      • UTF-8: E2 80 94
      • UTF-16: 20 14
    • U + 2030 POR SINAL MILLE:
      • Nº: 8240
      • UTF-8: E2 80 B0
      • UTF-16: 20 30
    • SINAL DO EURO U + 20AC:
      • Nº: 8364
      • UTF-8: E2 82 AC
      • UTF-16: 20 AC
    • SINAL DE MARCA COMERCIAL U + 2122:
      • Nº: 8482
      • UTF-8: E2 84 A2
      • UTF-16: 21 22
    • U + 2603 BONECO DE NEVE:
      • Nº: 9731
      • UTF-8: E2 98 83
      • UTF-16: 26 03
    • TELEFONE PRETO U + 260E:
      • Nº: 9742
      • UTF-8: E2 98 8E
      • UTF-16: 26 0E
    • GUARDA-CHUVA U + 2614 COM GOTAS DE CHUVA:
      • Nº: 9748
      • UTF-8: E2 98 94
      • UTF-16: 26 14
    • CARA DE SORRISO BRANCO DE U + 263A:
      • Nº: 9786
      • UTF-8: E2 98 BA
      • UTF-16: 26 3A
    • U + 2691 BANDEIRA PRETA:
      • Nº: 9873
      • UTF-8: E2 9A 91
      • UTF-16: 26 91
    • SÍMBOLO DE Átomo U + 269B
      • Nº: 9883
      • UTF-8: E2 9A 9B
      • UTF-16: 26 9B
    • AVIÃO U + 2708:
      • Nº: 9992
      • UTF-8: E2 9C 88
      • UTF-16: 27 08
    • U + 271E CRUZ LATINA BRANCA SOMBRA:
      • Nº: 10014
      • UTF-8: E2 9C 9E
      • UTF-16: 27 1E
    • CARA POSTAL U + 3020 MARCA:
      • Nº: 12320
      • UTF-8: E3 80 A0
      • UTF-16: 30 20
    • U + 8089 CJK IDEOGRAFO UNIFICADO-8089:
      • Nº: 32905
      • UTF-8: E8 82 89
      • UTF-16: 80 89
    • U + 1F4A9 PILO DE POO: 💩
      • Nº: 128169
      • UTF-8: F0 9F 92 A9
      • UTF-16: D8 3D DC A9
    • Foguete U + 1F680: 🚀
      • Nº: 128640
      • UTF-8: F0 9F 9A 80
      • UTF-16: D8 3D DE 80

Ok, eu estou me empolgando ...

Curiosidades:

basic6
fonte
As unidades de código em UTF-16 têm 16 bits de largura. Você mostrou a eles um espaço no meio, o que é enganoso. A representação UTF-16 para © deve ser 00A9preferivelmente em vez de 00 A9(que seria UTF-16BE).
Roland Illig
Qual é a diferença? BE não significa big endian? Ele escreveu em big endian e, portanto, um arquivo gravado em big endian UTF-16 seria o mesmo que UTF-16BE, certo?
HappyPandaFace
6
Correções: 1) ASCII é de 7 bits, um byte é de 8 bits e, portanto, é muito mais da metade. 2) Unicode define como codificar os pontos de código. UTF-8, UTF-16 e UTF-32 são definidos no Padrão Unicode.
Jonathan Rosenne
3
@ JonathanRosenne Eu acho que ele quis dizer que ele usa apenas metade dos valores possíveis representáveis ​​com 8 bits, não que ele use metade dos bits.
Aritz Lopez
2
Eu realmente gosto dos exemplos. Eles destacam por que alguém pode preferir UTF-16 ao invés de UTF-8, por exemplo. Os desenvolvedores de software diferente podem selecionar codificações diferentes com base nos quais caracteres Unicode têm maior probabilidade de serem usados. Na China / Japão, por exemplo, UTF-16 (2 bytes) faz mais sentido que UTF-8 para eles, porque os mesmos caracteres geralmente precisariam do dobro de bytes para codificar em UTF-8
mike
29

Simplesmente falar Unicodeé um padrão que atribui um número (chamado ponto de código) a todos os caracteres do mundo (ainda está em andamento).

Agora você precisa representar esses pontos de código usando bytes, chamados character encoding. UTF-8, UTF-16, UTF-6são maneiras de representar esses personagens.

UTF-8é uma codificação de caracteres multibyte. Os caracteres podem ter de 1 a 6 bytes (alguns deles podem não ser necessários no momento).

UTF-32 cada caractere possui 4 bytes por caractere.

UTF-16usa 16 bits para cada caractere e representa apenas parte dos caracteres Unicode chamados BMP (para todos os efeitos práticos, basta). Java usa essa codificação em suas cadeias.

Zimbabao
fonte
10
Unicode é um conjunto de códigos de 21 bits e 4 bytes são suficientes para representar qualquer caractere Unicode em UTF-8. UTF-16 usa substitutos para representar caracteres fora do BMP (plano multilíngue básico); ele precisa de 2 ou 4 bytes para representar qualquer caractere Unicode válido. O UCS-2 era a única variante de UTF-16 de 16 bits, sem suporte para substitutos ou caracteres fora do BMP.
22811 Jonathan Leffler
1
Você está certo. O original UTF-8 tinha 6 bytes para acomodar 32 bits. Na verdade, eu não queria complicar as coisas tanto quanto ele já foi confundido com doc wiki :)
Zimbabao
3
Esta resposta afirma que UTF-16 não pode codificar pontos de código BMP. Isso está incorreto, pois eles podem ser codificados da mesma forma que no UTF-8 usando pares substitutos. (Você deve estar pensando no UCS-2 desatualizado, antes de o Unicode 2.0 ser lançado, que codifica apenas pontos de código de 16 bits.) Além disso, o Java não usa o UTF-16, ele usa uma forma modificada em que o ponto do código 0 é codificado de forma diferente.
Rdb
@rdb - É o contrário. A resposta diz que UTF-16 representa o BMP.
Nicolas Barbulesco
3
Eu digitei incorretamente; Eu pretendia dizer "não BMP". O erro na resposta é que ele diz que UTF-16 representa caracteres BMP, o que é impreciso. O UTF-16 pode codificar todos os caracteres unicode - caracteres não BMP são codificados por pares substitutos. Talvez o atendedor tenha sido confundido com o UCS-2.
Rdb
17

Em UTF-8:

1 byte:       0 -     7F     (ASCII)
2 bytes:     80 -    7FF     (all European plus some Middle Eastern)
3 bytes:    800 -   FFFF     (multilingual plane incl. the top 1792 and private-use)
4 bytes:  10000 - 10FFFF

Em UTF-16:

2 bytes:      0 -   D7FF     (multilingual plane except the top 1792 and private-use )
4 bytes:   D800 - 10FFFF

Em UTF-32:

4 bytes:      0 - 10FFFF

10FFFF é o último ponto de código unicode por definição, e é definido dessa maneira porque é o limite técnico do UTF-16.

É também o maior ponto de código que o UTF-8 pode codificar em 4 bytes, mas a idéia por trás da codificação do UTF-8 também funciona para codificações de 5 e 6 bytes para cobrir pontos de código até 7FFFFFFF, ou seja. metade do que UTF-32 pode.

John
fonte
8

No Unicode, a resposta não é fácil. O problema, como você já apontou, são as codificações.

Dada qualquer sentença em inglês sem caracteres diacríticos, a resposta para UTF-8 seria de tantos bytes quanto caracteres e para UTF-16 seria o número de caracteres vezes dois.

A única codificação em que (a partir de agora) podemos fazer a declaração sobre o tamanho é UTF-32. Sempre há 32 bits por caractere, embora eu imagine que os pontos de código estejam preparados para um futuro UTF-64 :)

O que a torna tão difícil são pelo menos duas coisas:

  1. caracteres compostos, onde, em vez de usar a entidade de caracteres que já é acentuada / diacrítica (À), um usuário decidiu combinar o acento e o caractere base (`A).
  2. pontos de código. Os pontos de código são o método pelo qual as codificações UTF permitem codificar mais do que o número de bits que lhes dá seu nome normalmente permitiria. Por exemplo, UTF-8 designa certos bytes que, por si só, são inválidos, mas quando seguido por um byte de continuação válido permitirá descrever um caractere além do intervalo de 8 bits de 0 a 255. Veja os exemplos e codificações excessivas abaixo no artigo da Wikipedia sobre UTF-8.
    • A excelente exemplo dado há que o personagem € (ponto de código U+20ACpode ser representada quer como três bytes sequência E2 82 ACou quatro bytes sequência F0 82 82 AC.
    • Ambos são válidos, e isso mostra o quão complicada é a resposta ao falar sobre "Unicode" e não sobre uma codificação específica de Unicode, como UTF-8 ou UTF-16.
0xC0000022L
fonte
4

Bem, eu também peguei a página da Wikipedia e, na parte de introdução, vi "Unicode pode ser implementado por diferentes codificações de caracteres. As codificações mais usadas são UTF-8 (que usa um byte para qualquer caractere ASCII, que possui os mesmos valores de código na codificação UTF-8 e ASCII e até quatro bytes para outros caracteres), o agora obsoleto UCS-2 (que usa dois bytes para cada caractere, mas não pode codificar todos os caracteres no atual padrão Unicode) "

Como esta citação demonstra, seu problema é que você está assumindo que Unicode é uma maneira única de codificar caracteres. Na verdade, existem várias formas de Unicode e, novamente nessa citação, uma delas tem até 1 byte por caractere, exatamente como você está acostumado.

Portanto, sua resposta simples que você deseja é que ela varie.

Loduwijk
fonte
3

Para UTF-16, o caractere precisa de quatro bytes (duas unidades de código) se iniciar com 0xD800 ou superior; esse personagem é chamado de "par substituto". Mais especificamente, um par substituto tem a forma:

[0xD800 - 0xDBFF]  [0xDC00 - 0xDFF]

onde indica [...] uma unidade de código de dois bytes com o intervalo especificado. Qualquer coisa <= 0xD7FF é uma unidade de código (dois bytes). Qualquer coisa> = 0xE000 é inválido (exceto marcadores de lista técnica, sem dúvida).

Consulte http://unicodebook.readthedocs.io/unicode_encodings.html , seção 7.5.

prewett
fonte
1

Do Wiki:

UTF-8, uma codificação de largura variável de 8 bits que maximiza a compatibilidade com ASCII;

UTF-16, uma codificação de 16 bits e largura variável;

UTF-32, uma codificação de 32 bits e largura fixa.

Estas são as três codificações diferentes mais populares.

  • No UTF-8, cada caractere é codificado em 1 a 4 bytes (a codificação dominante)
  • Em UTF16, cada caractere é codificado em 1 a duas palavras de 16 bits e
  • no UTF-32, todos os caracteres são codificados como uma única palavra de 32 bits.
chikitin
fonte
1

Unicodeé um padrão que fornece um número único para cada caractere. Esses números únicos são chamados code points (que é apenas um código único) para todos os caracteres existentes no mundo (alguns ainda precisam ser adicionados).

Para propósitos diferentes, você pode precisar representá-lo code pointsem bytes (a maioria das linguagens de programação o faz), e é aqui que Character Encodingentra em ação.

UTF-8, UTF-16, UTF-32E assim por diante são todos Character Encodings, e pontos de código de Unicode são representados nestes codificações, de diferentes maneiras.


UTF-8 a codificação tem um comprimento de largura variável e os caracteres codificados nela podem ocupar 1 a 4 bytes, inclusive;

UTF-16possui um comprimento variável e os caracteres codificados podem ter 1 ou 2 bytes (8 ou 16 bits). Isso representa apenas parte de todos os caracteres Unicode chamados BMP (Basic Multilingual Plane) e é suficiente para quase todos os casos. Java usa UTF-16codificação para suas strings e caracteres;

UTF-32 possui comprimento fixo e cada caractere ocupa exatamente 4 bytes (32 bits).

Giorgi Tsiklauri
fonte