UTF-8 (abreviação de Universal Character Set Transformation Format - 8 bits ) é uma codificação de caracteres de computador projetada para codificar o conjunto de caracteres do "repertório de caracteres codificados universal", originalmente desenvolvido pela ISO no padrão. Internacional ISO / IEC 10646 , agora totalmente compatível com o padrão Unicode , embora permaneça compatível com o padrão ASCII limitado ao inglês básico, mas amplamente utilizado por décadas.
UTF-8 é usado por 82,2% dos sites em dezembro de 2014, 87,6% em 2016, 90,5% em 2017, 93,1% em fevereiro de 2019 e quase 95,2% em outubro de 2020. Por sua natureza, o UTF-8 é cada vez mais usado na Internet e em sistemas que precisam trocar informações. É também a codificação mais usada em GNU , Linux e sistemas compatíveis para gerenciar textos e suas traduções da forma mais simples possível em todos os sistemas de escrita e todos os alfabetos do mundo.
UTF-8 é um "formato de transformação" originalmente do trabalho para o padrão ISO / IEC 10646 , ou seja, UTF-8 define uma codificação para qualquer ponto de código escalar ( caractere abstrato ou "não caractere") do Conjunto de caracteres universais ( UCS ) diretório. Este diretório agora é comum ao padrão ISO / IEC 10646 (desde sua revisão 1) e ao padrão Unicode (desde sua versão 1.1).
O UTF-8 é oficialmente definido na norma ISO / IEC 10646 desde sua adoção em uma emenda publicada em 1996. Também foi descrito na norma Unicode e faz parte desta norma desde a versão 3.0 publicada em 2000. Em 1996 foi publicada a RFC 2044 (" UTF-8, um formato de transformação da ISO 10646 ") a fim de fornecer uma especificação acessível de UTF-8 e iniciar sua padronização dentro da Internet Engineering Task Force (IETF). Esta RFC foi revisada em 1998 ( RFC 2279) e finalmente em 2003 ( RFC 3629), esta última versão tornando o UTF-8 um dos padrões da Internet (STD 63).
Tecnicamente, isso envolve a codificação de caracteres Unicode na forma de sequências de um a quatro pontos de código de um byte cada. O padrão Unicode define, entre outras coisas, um conjunto (ou diretório) de caracteres. Cada caractere é identificado neste conjunto por um índice inteiro também chamado de “ ponto de código ”. Por exemplo, o caractere “€” ( euro ) é o 8365 th personagem do diretório Unicode, o seu índice, ou ponto de código, é, portanto, 8364 (0x20AC) (começamos a contagem de 0).
O diretório Unicode pode conter mais de um milhão de caracteres, o que é muito grande para ser codificado como um único byte (limitado a valores entre 0 e 255). O padrão Unicode, portanto, define métodos padronizados para codificar e armazenar esse índice na forma de uma sequência de bytes: UTF-8 é um deles, junto com UTF-16 , UTF-32 e suas várias variantes.
A principal característica do UTF-8 é ser compatível com as versões anteriores do padrão ASCII, ou seja, qualquer caractere ASCII é codificado em UTF-8 na forma de um único byte, idêntico ao código ASCII. Por exemplo, “A” (A maiúsculo) tem o código ASCII 65 (0x41) e é codificado em UTF-8 pelo byte 65. Cada caractere cujo ponto de código é maior que 127 (0x7F) (caractere não ASCII) é código em 2 para 4 bytes . O caractere “€” (euro) é codificado, por exemplo, em 3 bytes : 226, 130 e 172 (0xE2, 0x82 e 0xAC).
O número (valor escalar) de cada ponto de código no Conjunto de caracteres universais (UCS) é dado pela norma ISO / IEC 10646 que atribui um ponto de código a cada caractere válido e permite sua codificação atribuindo um valor escalar idêntico ao ponto de código ; este padrão está incluído no padrão Unicode (que usa o mesmo diretório desde a versão 1.1).
Todos os " pontos de código " de U + 0000 a U + D7FF e de U + E000 a U + 10FFFF são representáveis em UTF-8 - mesmo aqueles atribuídos a "não-caracteres" ( não-caractere ) e todos aqueles ainda não atribuídos - e apenas aqueles. Os únicos pontos de código válidos no espaço UCS e que não devem ser representados em UTF-8 são aqueles atribuídos aos "pontos de meio-código " ( substitutos em inglês), porque eles não são representáveis de uma forma. Bijetivo na codificação UTF-16 e também não são caracteres por si só: ao contrário de outros pontos de código, os meio-códigos, portanto, não têm um " valor escalar " definido.
O código de ponto tendo um valor escalar de 0 a 127 (pontos de código U + 0000 U + 007F, atribuídos aos caracteres do conjunto codificado em 7 bits em ASCII) são codificados em um byte do qual o bit mais significativo é zero.
Os outros pontos de código (atribuídos ou não a caracteres) com um valor escalar superior a 127 (exceto aqueles aos quais são atribuídos "meio-códigos" que não são eles próprios caracteres) são codificados em vários bytes, cada um tendo o seu próprio. Diferente de zero bit mais significativo: os bits mais significativos do primeiro byte da sequência codificada formam uma sequência de 1's de comprimento igual ao número total de bytes (pelo menos 2) usados para toda a sequência seguida por um 0 e os bytes subsequentes necessários têm seus dois bits mais significativos definidos como 10.
Caracteres codificados | Representação binária UTF-8 | Primeiro byte válido (hexadecimal) | Significado |
---|---|---|---|
U + 0000 a U + 007F | 0 xxxxxxx | 00 a 7F | 1 byte, codificando 7 bits |
U + 0080 a U + 07FF | 11 0 xxxxx 10 xxxxxx | C2 para DF | 2 bytes, codificação de 11 bits |
U + 0800 a U + FFFF | 111 0 xxxx 10 xxxxxx 10 xxxxxx | E0 para EF | 3 bytes, codificação de 16 bits |
U + 10000 a U + 10FFFF | 1111 0 xxx 10 xxxxxx 10 xxxxxx 10 xxxxxx | F0 a F4 | 4 bytes, codificação de 21 bits |
Esse princípio poderia ser estendido para oito bytes para um único ponto de código (para representar pontos de código de até 42 bits), mas a versão padronizada atual do UTF-8 define o limite para quatro.
A codificação proíbe a representação de pontos de código reservados para meio-códigos (que não possuem um valor escalar definido, a fim de preservar a compatibilidade com UTF-16 que também não permite sua representação). No entanto, ele autoriza a representação de pontos de código atribuídos a não caracteres (embora sua presença seja proibida em um texto conforme).
Modelo | Personagem |
Ponto de código (hexadecimal) |
Valor escalar | Codificação UTF-8 | ||
---|---|---|---|---|---|---|
decimal | binário | binário | hexadecimal | |||
Ao controle | [NÃO] | U + 0000 | 0 | 0 | 0 0000000 | 00 |
[NÓS] | U + 001F | 31 | 1111 | 0 0011111 | 1F | |
Texto | [SP] | U + 0020 | 32 | 100000 | 0 0100000 | 20 |
NO | U + 0041 | 65 | 100.0001 | 0 100.0001 | 41 | |
~ | U + 007E | 126 | 111 1110 | 0 1111110 | 7E | |
Ao controle | [DO] | U + 007F | 127 | 111 1111 | 0 1111111 | 7F |
[ALMOFADA] | U + 0080 | 128 | 000 1000 0000 | 110 000 10 10 000 000 | C2 80 | |
[APC] | U + 009F | 159 | 000 1001 1111 | 110 000 10 10 011 111 | C2 9F | |
Texto | [NBSP] | U + 00A0 | 160 | 000 1010 0000 | 110 000 10 10 100 000 | C2 A0 |
é | U + 00E9 | 233 | 000 1110 1001 | 110 000 11 10 101 001 | C3 A9 | |
߿ | U + 07FF | 2047 | 111 1111 1111 | 110 111 11 10 111 111 | DF BF | |
ࠀ | U + 0800 | 2048 | 1000 0000 0000 | 1110 0000 10 1000 00 10 000000 | E0 A0 80 | |
€ | U + 20AC | 8 364 | 100000 10101100 | 1110 0010 10 0000 10 10 101100 | E2 82 AC | |
| U + D7FF | 55.295 | 1101 0111 1111 1111 | 1110 1101 10 0111 11 10 111111 | ED 9F BF | |
Meio codet | U + D800 | (nada) | (codificação proibida) | |||
U + DFFF | ||||||
Uso privado | [] | U + E000 | 57.344 | 1110 0000 0000 0000 | 1110 1110 10 0000 00 10 0000000 | EE 80 80 |
[] | U + F8FF | 63.743 | 1111 1000 1111 1111 | 1110 1111 10 1000 11 10 111111 | EF A3 BF | |
Texto | U + F900 | 63 744 | 1111 1001 0000 0000 | 1110 1111 10 1001 00 10 000 000 | EF A4 80 | |
﷏ | U + FDCF | 64 975 | 1111 1101 1100 1111 | 1110 1111 10 1101 11 10 001111 | EF B7 8F | |
Não-personagens | U + FDD0 | 64 976 | 1111 1101 1101 0000 | 1110 1111 10 1101 11 10 010000 | EF B7 90 | |
U + FDEF | 65.007 | 1111 1101 1110 1111 | 1110 1111 10 1101 11 10 101111 | EF B7 AF | ||
Texto | ﷰ | U + FDF0 | 65.008 | 1111 1101 1111 0000 | 1110 1111 10 1101 11 10 110000 | EF B7 B0 |
U + FFFD | 65.533 | 1111 1111 1111 1101 | 1110 1111 10 1111 11 10 111101 | EF BF BD | ||
Não-personagens | U + FFFE | 65.534 | 1111 1111 1111 1110 | 1110 1111 10 1111 11 10 111110 | EF BF BE | |
U + FFFF | 65.535 | 1111 1111 1111 1111 | 1110 1111 10 1111 11 10 111111 | EF BF BF | ||
Texto | ? | U + 10.000 | 65.536 | 1 0000 0000 0000 0000 | 11 110 000 10 01 0000 10 0000 00 10 000000 | F0 90 80 80 |
? | U + 1D11E | 119.070 | 1 1101 0001 0001 1110 | 11 110 000 10 01 1101 10 0001 00 10 011 110 | F0 9D 84 9E | |
? | U + 1FFFD | 131.069 | 1 1111 1111 1111 1101 | 11110 000 10 01 1111 10 1111 11 10 111 101 | F0 9F BF BD | |
Não-personagens | U + 1FFFE | 131.070 | 1 1111 1111 1111 1110 | 11110 000 10 01 1111 10 1111 11 10 111 110 | F0 9F BF BE | |
U + 1FFFF | 131.071 | 1 1111 1111 1111 1111 | 11 110 000 10 01 1111 10 1111 11 10 111111 | F0 9F BF BF | ||
Texto | ? | U + 20.000 | 131.072 | 10 0000 0000 0000 0000 | 11 110 000 10 10 0000 10 0000 00 10 000000 | F0 A0 80 80 |
? | U + 2FFFD | 196.605 | 10 1111 1111 1111 1101 | 11110 000 10 10 1111 10 1111 11 10 111 101 | F0 AF BF BD | |
Não-personagens | U + 2FFFE | 196.606 | 10 1111 1111 1111 1110 | 11110 000 10 10 1111 10 1111 11 10 111 110 | F0 AF BF BE | |
U + 2FFFF | 196.607 | 10 1111 1111 1111 1111 | 11 110 000 10 10 1111 10 1111 11 10 111111 | F0 AF BF BF | ||
... outros planos reservados ... | ||||||
Especiais | ? | U + E0000 | 917.504 | 1110 0000 0000 0000 0000 | 11110 011 10 10 0000 10 0000 00 10 000000 | F3 A0 80 80 |
? | U + EFFFD | 983.037 | 1110 1111 1111 1111 1101 | 11110 011 10 10 1111 10 1111 11 10 111101 | F3 AF BF BD | |
Não-personagens | U + EFFFE | 983.038 | 1110 1111 1111 1111 1110 | 11110 011 10 10 1111 10 1111 11 10 111110 | F3 AF BF BE | |
U + EFFFF | 983.039 | 1110 1111 1111 1111 1111 | 11110 011 10 10 1111 10 1111 11 10 111111 | F3 AF BF BF | ||
Uso privado | [?] | U + F0000 | 983.040 | 1111 0000 0000 0000 0000 | 11110 011 10 11 0000 10 0000 00 10 000000 | F3 B0 80 80 |
[ ] | U + FFFFD | 1.048.573 | 1111 1111 1111 1111 1101 | 11110 011 10 11 1111 10 1111 11 10 111101 | F3 BF BF BD | |
Não-personagens | U + FFFFE | 1.048.574 | 1111 1111 1111 1111 1110 | 11110 011 10 11 1111 10 1111 11 10 111110 | F3 BF BF BE | |
U + FFFFF | 1.048.575 | 1111 1111 1111 1111 1111 | 11110 011 10 11 1111 10 1111 11 10 111111 | F3 BF BF BF | ||
Uso privado | [?] | U + 100.000 | 1.048.576 | 1 0000 0000 0000 0000 0000 | 11110 100 10 00 0000 10 0000 00 10 000000 | F4 80 80 80 |
[?] | U + 10FFFD | 1.114.109 | 1 0000 1111 1111 1111 1101 | 11110 100 10 00 1111 10 1111 11 10 111101 | F4 8F BF BD | |
Não-personagens | U + 10FFFE | 1.114.110 | 1 0000 1111 1111 1111 1110 | 11110 100 10 00 1111 10 1111 11 10 111110 | F4 8F BF BE | |
U + 10FFFF | 1.114.111 | 1 0000 1111 1111 1111 1111 | 11110 100 10 00 1111 10 1111 11 10 111111 | F4 8F BF BF |
Em qualquer sequência de caracteres codificada em UTF-8, notamos que:
O maior ponto de atribuível código válido para um caractere válido não privado é U + EFFFD no 15 º Plano (que ainda não está atribuído, mas pode tornar-se no futuro), mas UTF-8 pode ser usado também, de uma forma padrão, para representar qualquer caractere válido para uso privado (em um dos três intervalos U + E000 a U + F8FF, U + F0000 a U + FFFFD e U + 100000 a U + 10FFFD).
A aceitação ou não de não caracteres ou caracteres de uso privado é deixada para os aplicativos ou protocolos de transporte de texto. No entanto, não-caracteres não são normalmente aceitos em textos estritamente em conformidade com o padrão Unicode ou ISO / IEC 10646 .
Alguns aplicativos impõem restrições adicionais aos pontos de código que podem ser usados (por exemplo, os padrões HTML e XML proíbem, em qualquer documento em conformidade com essas especificações, a presença da maioria dos caracteres de controle entre U + 0000 e U + 001F e entre U + 0080 e U + 009F, fora do controle da guia U + 0009, considerado um caractere em branco, e também proíbe os não caracteres ).
Qualquer ponto de código é sempre representado exatamente pela mesma sequência binária, qualquer que seja sua posição relativa no texto, e essas sequências são autossincronizadas na posição indivisa dos pontos de código significativos (aqui os bytes: podemos sempre saber se um byte começa ou não um seqüência binária efetiva); essa codificação, portanto, permite algoritmos de pesquisa de texto rápidos, como o algoritmo de Boyer-Moore .
Este nem sempre é o caso com codificações contextuais (que geralmente usam compressão de dados , por exemplo SCSU definido na nota técnica do padrão UTS # 6 opcional que complementa o padrão Unicode) e que pode exigir a leitura do texto completamente desde o início., Nem com base em codificações em mais de uma única variável de estado (ou que incorporem códigos de redundância adicionais); na melhor das hipóteses, algumas dessas codificações podem exigir o uso de algoritmos de ressincronização complexos, muitas vezes baseados em heurísticas que podem falhar ou levar a falsas interpretações se o texto não for lido desde o início (por exemplo, BOCU -1).
Princípio e exclusividade da codificaçãoNa tabela acima, vemos que o caractere “€” é encontrado no ponto de código U + 20AC, seja no decimal 8364 ou em binário: 100.000 10101100.
Este último número possui dígitos binários significativos, portanto, pelo menos 14 bits são necessários para codificar o caractere "€". O padrão apresentado acima realmente requer três bytes para representar esses caracteres.
Com quatro bytes disponíveis, seria possível colocar de acordo com este padrão até 21 bits , de modo a representar o caractere “€” por 00000 00 100000 10101100, adicionando 7 zeros à esquerda . No entanto, o padrão impõe que um programa que decodifica UTF-8 não deve aceitar strings de byte desnecessariamente longas como neste exemplo, por razões de segurança (evite o uso de testes de substring muito tolerantes). Assim, “€” será codificado: 11100010 10000010 10101100, mas a codificação 11110000 10000010 10000010 10101100, deduzida da representação de “€” em 21 bits , embora inequívoca, não deve ser usada.
Essa forma mais longa do que o necessário é chamada overlong em inglês . Tais formulários (inicialmente autorizados em especificações antigas antes de serem sucessivamente padronizados pela RFC inicial publicada pelo X / Open Consortium , depois em paralelo pelo padrão ISO 10646 e o padrão Unicode) são proibidos e devem ser tratados como inválidos.
A codificação é preditiva e sempre permite encontrar a posição do primeiro byte de uma sequência que representa um ponto de código, a partir do valor de qualquer byte e da leitura de um número limitado de bytes vizinhos, nas duas direções de leitura (ele será sempre o próprio byte, ou o primeiro elegível em um dos 1 a 3 bytes vizinhos).
Essas sequências são consideradas mal formadas . (Consulte a referência acima, especialmente a segunda tabela na cláusula de conformidade D36 da norma ou o artigo Unicode ).
Por outro lado, pontos de código reservados (ainda não atribuídos aos caracteres) são autorizados (mesmo que a interpretação dos caracteres possa permanecer ambígua): cabe aos aplicativos decidir se esses caracteres são aceitáveis ou não, sabendo que o mesmo os aplicativos provavelmente continuarão a ser usados, embora essas posições tenham sido atribuídas nos padrões Unicode e ISO 10646 a caracteres novos e totalmente válidos.
Da mesma forma, outros pontos de código atribuídos permanentemente a outros " não-caracteres " são proibidos em textos em conformidade com a ISO / IEC 10646 ou com o padrão Unicode : por exemplo U + x FFFE a U + x FFFF (onde x indica um número de plano hexadecimal de 0 a 10). Mas eles permanecem codificáveis e decodificáveis como tal em UTF-8 ( não-caracteres estão disponíveis para aplicativos que podem fazer uso deles em APIs internas, por exemplo, como códigos intermediários necessários para a implementação de certos processos).
A restrição do espaço de representação a apenas pontos de código menores ou iguais a U + 10FFFF (não incluindo os pontos de código atribuídos a pontos de meio-código ) nem sempre foi aplicada:
Um texto em US-ASCII é codificado de forma idêntica em UTF-8 (quando o BOM não é usado).
Como um caractere é dividido em uma sequência de bytes (não em palavras de vários bytes), não há problema de endianness ( endianness em inglês).
Para a maioria das linguagens de script latino, arquivos de dados digitais ou códigos-fonte de programas ou muitos protocolos de comunicação textual (como FTP , HTTP ou MIME ), que usam caracteres extensivamente (ou às vezes apenas em partes) US-ASCII, UTF-8 requer menos bytes do que UTF-16 ou UTF-32 .
Muitas técnicas de programação de computador que são válidas com caracteres de byte único uniformes permanecem válidas com UTF-8, incluindo:
Esta é uma codificação de sincronização automática (ao ler um único byte sabemos se é o primeiro de um caractere ou não).
Os pontos de código são representados em UTF-8 por sequências de bytes de tamanhos variados (bem como em UTF-16), o que torna algumas operações em cadeias de pontos de código mais complicadas: calcular o número de pontos de código; posicionamento a uma determinada distância (expressa em número de pontos de código) em um arquivo de texto e, em geral, qualquer operação que requeira acesso ao ponto de código da posição N em uma cadeia.
Um tamanho variável dos caracteres de uma string impede o uso de algoritmos eficientes em termos de comparações de strings, como o algoritmo Knuth-Morris-Pratt e, portanto, penaliza fortemente o processamento de dados em massa como na exploração de bancos de dados. Esse problema, entretanto, está mais relacionado a aspectos de padronização do que de codificação.
Para idiomas que usam muitos caracteres fora de US-ASCII , o UTF-8 ocupa muito mais espaço. Por exemplo, ideogramas comuns usados em textos em idiomas asiáticos como chinês ou japonês ( kanji , por exemplo) usam 3 bytes em UTF-8 contra 2 bytes em UTF-16.
Em geral, as escritas que usam muitos pontos de código de valor igual ou superior a U + 0800 ocupam mais memória do que se fossem codificadas com UTF-16 (UTF-32 será mais eficiente apenas para textos que usam principalmente escritas. antigo ou raro codificado fora do plano multilíngue básico, ou seja, de U + 10000, mas também pode se mostrar útil localmente em certos processos para simplificar os algoritmos, pois os caracteres ali sempre têm um tamanho fixo, convertendo entrada ou saída dados de ou para UTF-8 ou UTF-16 sendo triviais).
Pelo seu sistema de codificação, era possível representar um código de diferentes maneiras em UTF-8, o que poderia representar um problema de segurança: um programa mal escrito pode aceitar um certo número de representações UTF-8, normalmente inválidas de acordo com a RFC 3629 e nas especificações (agora equivalentes entre si) publicadas pela ISO 10646 e Unicode; mas este não era o caso de acordo com a especificação original, que permitia que eles fossem convertidos em um único caractere.
Assim, um software que detecta certas cadeias de caracteres (para evitar injeções de SQL , por exemplo) pode falhar em sua tarefa (este não é mais o caso se a conformidade da codificação com a definição estrita e padronizada de UTF-8 for verificada. tudo).
Vamos dar um exemplo de um caso real de um vírus atacando servidores HTTP na Web em 2001 ( (en) Crypto-Gram: 15 jul 2000 Microsoft IIS e PWS vulnerabilidade Unicode de passagem de diretório estendido Microsoft IIS Vulnerabilidade 4.0 / 5.0 Web Diretório Traversal ) . Uma sequência a ser detectada poderia ser “/../” representada em ASCII ( a fortiori em UTF-8) pelos bytes “ 2F 2E 2E 2F ” em notação hexadecimal . No entanto, uma forma incorreta de codificar essa string em UTF-8 seria " 2F C0 AE 2E 2F ", também chamada de forma overlong . Se o software não for escrito com cuidado para rejeitar essa cadeia, por exemplo, colocando-a na forma canônica , uma violação de segurança potencial é aberta. Esse ataque é chamado de travessia de diretório .
O software que aceita texto codificado em UTF-8 foi blindado para rejeitar sistematicamente esses formulários longos porque eles não estão em conformidade com o padrão: ou o texto inteiro é rejeitado; mas às vezes as sequências inválidas são substituídas por um caractere de substituição (geralmente U + FFFD se o aplicativo aceita e processa esse caractere normalmente; às vezes, um ponto de interrogação ou o caractere de controle de substituição SUB U + 001A de ASCII, que pode representar outros problemas de compatibilidade); com menos frequência, essas sequências proibidas são eliminadas silenciosamente (o que é muito pouco recomendado).
UTF-8 só pode representar o caractere de controle nulo (U + 0000) com um único byte nulo, o que apresenta problemas de compatibilidade com o processamento de strings que não codificam separadamente seu comprimento efetivo porque esse byte nulo não representa então nenhum caractere, mas o final da string (caso muito comum na linguagem C ou C ++ e nas APIs de sistemas operacionais). Se um caracter nulo deve ser armazenado em um texto em tais sistemas, será necessário recorrer a um sistema de escape, específico para este idioma ou sistema, antes de codificar em UTF-8 o texto assim transformado. Na prática, nenhum texto válido deve conter esse caractere. Outra solução é usar uma das sequências proibidas na codificação UTF-8 padrão para codificar o caractere por esta sequência; mas o texto assim codificado não estará em conformidade com a codificação UTF-8 padrão, mesmo se a codificação assim modificada permanecer um formato de transformação universal conforme (que, no entanto, não deve ser designado como "UTF-8"). Consulte a seção abaixo sobre variantes não padrão baseadas em UTF-8.
Usar UTF8, como qualquer codificação de pitch variável, em um banco de dados apresenta vários problemas de desempenho.
Operações de comparação (=,>, <, BETWEEN, LIKE ...), classificação (ORDER BY), agrupamento (GROUP BY), como operações de desduplicação (DISTINCT) com base na semântica da informação, são impossíveis de serem gerenciadas diretamente em UTF8 .
De fato, para cadeias de caracteres compreendendo o mesmo número de letras (por exemplo CHAR (8)), o número de bytes pode ser diferente (em particular por causa dos caracteres diacríticos: acentos, ligaduras ...), os algoritmos usados devem, para na maior parte, realiza um alinhamento antes de poder operar, o que induz um custo de processamento adicional não desprezível.
Por exemplo, o DBMS MySQL / MariaDB optou por representar os caracteres das strings apresentadas como UTF8 usando sistematicamente 3 bytes por caractere. As consequências são as seguintes: triplicar o volume de dados e dividir por três o comprimento potencial das chaves de índice em comparação com a codificação ASCII e aumentar os tempos de execução para comparações, classificações, agrupamentos ou desduplicação. A string é finalmente retornada no formato UTF8 após limpar os bytes desnecessários.
Outros SGBDs, como o Microsoft SQL Server, optaram por compactar o suporte UTF8 inserindo os caracteres adicionais em uma codificação de 2 bytes, com base em UNICODE, aproveitando os espaços deixados vazios pela especificação. O esforço adicional para a tradução em UTF8 reside apenas na recodificação dos caracteres codificados em 2 bytes e na expansão daqueles codificados em 3.
UTF-8 foi inventado por Kenneth Thompson durante um jantar com Rob Pike por pertoSetembro de 1992. Chamado FSS-UTF então , foi imediatamente usado no sistema operacional Plan 9 em que estavam trabalhando. Uma restrição a ser resolvida era codificar os caracteres nulos e '/' como em ASCII e que nenhum byte que codifica outro caractere tem o mesmo código. Assim, os sistemas operacionais UNIX podem continuar a procurar esses dois caracteres em uma string sem adaptação de software.
O FSS-UTF foi o assunto de um padrão X / Open preliminar de 1993 que foi proposto à ISO. Este último o adotou como parte do padrão ISO / IEC 10646 com o nome primeiro de UTF-2 e, finalmente, UTF-8.
Gráfico mostrando o uso de UTF-8 (azul claro) excedendo outras codificações de caracteres de texto principais na Web. Em 2010, a prevalência de UTF-8 era de cerca de 50%, mas em 2016 era cerca de 90%. |
Estatísticas que refletem as tecnologias usadas nos sites determinadas a partir de técnicas de reconhecimento para diferentes padrões, incluindo elementos HTML, tags HTML específicas (como a "metatag do gerador", o código JavaScript, o código CSS, a estrutura dos URLs do site, links externos, cabeçalhos HTTP, por exemplo, cookies, respostas HTTP a certas solicitações, como compactação.
Estatísticas baseadas em uma amostra dos 10 milhões de sites principais de acordo com Alexa. O total não chega a 100% porque alguns servidores utilizam mais de uma tecnologia. |
Fonte w3techs |
A codificação FSS-UTF original destinava-se a substituir a codificação multibyte UTF-1 inicialmente proposta pela ISO 10646. Essa codificação inicialmente permissiva permitia várias representações binárias para o mesmo caractere (isso era proibido na versão padronizada no RFC publicado pela X / Open Consortium e aprovado por Kenneth Thompson).
Além disso, poderia (em uma versão preliminar não retida) codificar todos os caracteres cujo valor de ponto de código compreendia até 32 bits , definindo um oitavo tipo de byte (em sequências de até 6 bytes ), em vez dos 7 tipos de bytes finalmente retidos para codificar (em sequências também compreendendo até 6 bytes ) apenas o código aponta até 31 bits na versão inicial do UTF-8 (publicado pelo Consortium X / Open sob o nome FSS-UTF, então proposto pelo comitê técnico da ISO 10646 como a proposta “UTF-2” então ainda em competição com a proposta “UTF-1”, até que a proposta UTF-2 seja mantida e adote o nome UTF-8 já retido e usado no X / Open e Plano 9).
Esta codificação UTF-8 foi ainda mais restrita quando Unicode e ISO 10646 concordaram em alocar caracteres apenas nos primeiros 17 planos, a fim de manter a compatibilidade com UTF-16 indefinidamente (sem ter que modificá-lo), restringindo sequências até 'a apenas 4 bytes e usando apenas os primeiros 5 dos 7 tipos de bytes (o que exigia a definição de novos valores de bytes inválidos e certas sequências de bytes, porém válidas individualmente).
O IETF agora requer que UTF-8 seja suportado por padrão (e não simplesmente como uma extensão suportada) por todos os novos protocolos de comunicação da Internet (publicados em seu número RFC ) que trocam texto (os protocolos mais antigos, entretanto, não foram modificados para tornar este suporte obrigatório, mas somente se possível estendido, para suportá-lo opcionalmente, se isso produzir incompatibilidades ou introduzir novos riscos de segurança: é o caso dos protocolos da Internet amplamente utilizados como DNS , HTTP , FTP , Telnet e HTML em suas versões iniciais então ainda não padronizado por W3C e ISO).
Tornou-se essencial, principalmente nos principais softwares de comunicação web e nos sistemas operacionais atuais:
No entanto, as variantes de UTF-8 (com base nas possibilidades de codificação da versão irrestrita inicial) continuaram a ser usadas (principalmente na implementação da serialização de string Java) para permitir a codificação como um escape multibyte de certos caracteres ASCII reservados normalmente codificados em um único byte (por exemplo, o caractere nulo).
Além disso, alguns sistemas usam strings irrestritas: por exemplo, Java (e outras linguagens, incluindo bibliotecas de manipulação de string em C, PHP, Perl, etc.) representam caracteres com unidades de codificação em 16 bits (o que torna possível armazenar strings usando UTF -16 codificação, mas sem as restrições de validade impostas pelo UTF-16 sobre valores proibidos e emparelhamento na ordem de "meio-códigos" ou substitutos ); neste caso, as unidades de codificação são tratadas como valores binários e é necessário serializá-las individualmente (independentemente de sua possível interpretação como caracteres ou como meios-pontos do código). Neste caso, cada unidade de codificação de 16 bits que representa um "caractere" (irrestrito) é serializada na forma de sequências compreendendo até 3 bytes cada, e alguns bytes proibidos pela implementação (por exemplo, caracteres nulos ou a barra de fração ' / 'em um sistema de arquivos ou outros caracteres de byte único em outros protocolos) são codificados como sequências de escape de byte duplo, nenhum dos quais é zero, simplesmente usando o princípio de codificação da primeira especificação do FSS-UTF (antes daquele retido pelo X / Open Consortium em seu RFC inicial, onde essas fugas foram especificamente proibidas e assim permaneceram).
Antes da adoção da proposta UTF-2 mantida para UTF-8, havia também uma variante UTF-1, onde múltiplas codificações não eram possíveis, mas exigiam codificação / decodificação mais difícil para levar em consideração a posição de cada byte. E o uso uma série de valores "mágicos".
Essas variantes não devem ser chamadas de "UTF-8".
Uma dessas variantes não padronizadas foi, no entanto, objeto de uma padronização posterior (como uma alternativa ao UTF-16 e usando pares de "meio-códigos" cada um codificado em 3 bytes; ou seja, 6 bytes no total em vez de 4 com UTF-8): consulte CESU-8 .
Exemplo de uma variante usada em JavaPor exemplo, as APIs de integração de máquina virtual Java (para JNI, Java Native Interface ou para a serialização de classes pré-compiladas), que permitem a troca de strings Java irrestritas na forma de sequências de bytes (a fim de manipulá-las, usar ou produzir por código nativo, ou para armazenamento como um arquivo nativo codificado em strings de bytes), são sufixados por "UTFChars" ou "UTF", mas esta codificação específica de Java não é UTF-8 (a documentação da Sun refere-se a ela como UTF modificado , mas alguns documentos JNI mais antigos ainda se referem incorretamente a essa codificação como UTF-8 , o que produziu algumas anomalias comportamentais de algumas bibliotecas JNI nativas, especialmente com APIs do sistema. plataformas nativas mais antigas que não suportam nativamente codificações de caracteres acima de 8 bits ), porque:
Consequentemente :
Esses processos podem ser ineficientes para fazer a interface de grandes quantidades de texto porque exigem a alocação de buffers de memória adicionais para, então, fazer a interface em código nativo com o sistema ou interfaces de rede que aceitam apenas UTF-8 padrão.
No entanto JNI também fornece uma API binária mais eficiente, permitindo usar UTF-16 diretamente, capaz de interagir diretamente com protocolos de rede e interfaces de sistema (por exemplo, APIs do Windows) que suportam UTF-16, sem exigir qualquer alocação de memória adicional para transcodificação (apenas a conformidade check pode ser necessário, principalmente para verificar o texto codificado para o emparelhamento correto do meio-código ou substituto , que Java (como também outras linguagens de programação) permite manipular sem restrição de validade em suas próprias cadeias de caracteres não destinadas a armazenar apenas textos compatível com UCS). Esta API binária é suportada em todos os sistemas em que o Java foi portado, mesmo aqueles cujo sistema operacional não oferece uma API de texto Unicode (o suporte pode ser feito no aplicativo nativo do host ou usando as bibliotecas padrão fornecidas com o JVM ou outro nativo independente bibliotecas.