Qual é a diferença entre UTF-8 e UTF-8 sem BOM?

818

O que há de diferente entre UTF-8 e UTF-8 sem uma lista técnica ? Qual é melhor?

simples
fonte
77
O UTF-8 pode ser detectado automaticamente melhor pelo conteúdo do que pela BOM. O método é simples: tente ler o arquivo (ou uma string) como UTF-8 e, se for bem-sucedido, suponha que os dados sejam UTF-8. Caso contrário, assuma que seja CP1252 (ou alguma outra codificação de 8 bits). Qualquer codificação não UTF-8 de oito bits quase certamente conterá sequências que não são permitidas pelo UTF-8. O ASCII puro (7 bits) é interpretado como UTF-8, mas o resultado também é correto.
306 Tronic
39
A digitalização de arquivos grandes em busca de conteúdo UTF-8 leva tempo. Uma lista técnica torna esse processo muito mais rápido. Na prática, você frequentemente precisa fazer as duas coisas. O culpado hoje em dia é que ainda muito conteúdo de texto não é Unicode, e ainda encontro ferramentas que dizem que usam Unicode (por exemplo, UTF-8), mas emitem seu conteúdo em uma página de código diferente.
Jeroen Wiert Pluimers
10
@Tronic Eu realmente não acho que "melhor" se encaixe neste caso. Depende do ambiente. Se você tiver certeza de que todos os arquivos UTF-8 estão marcados com uma BOM, a verificação da BOM é a maneira "melhor" , porque é mais rápida e confiável.
mg30rg
32
UTF-8 não possui uma lista técnica. Quando você coloca um ponto de código U + FEFF no início de um arquivo UTF-8, deve-se tomar cuidado especial para lidar com ele. Essa é apenas uma daquelas mentiras de nomes da Microsoft, como chamar uma codificação "Unicode" quando não existe.
Tchrist #
7
"O Mainframe moderna (e AIX) é pouco endian UTF-8 ciente" UTF-8 não tem um endedness ! não há embaralhamento de bytes para colocar pares ou grupos de quatro na "ordem" correta para um sistema específico! Para detectar uma sequência de bytes UTF-8, pode ser útil observar que o primeiro byte de uma sequência de "bytes múltiplos" "codepoint" (os bytes que NÃO são ASCII "simples") possui o bit MS definido e todos os um a três outros bits sucessivamente menos significativos seguidos por um bit de redefinição. O número total desses bits definidos é um a menos bytes que estão nessa codepoint e todos terão o conjunto MSB ...
SlySven

Respostas:

773

A lista técnica UTF-8 é uma sequência de bytes no início de um fluxo de texto ( 0xEF, 0xBB, 0xBF) que permite ao leitor adivinhar com mais segurança um arquivo como sendo codificado em UTF-8.

Normalmente, a BOM é usada para sinalizar o endianness de uma codificação, mas como o endianness é irrelevante para UTF-8, o BOM é desnecessário.

De acordo com o padrão Unicode , o BOM para arquivos UTF-8 não é recomendado :

2.6 Esquemas de codificação

... O uso de uma BOM não é necessário nem recomendado para UTF-8, mas pode ser encontrado em contextos em que os dados UTF-8 são convertidos de outros formulários de codificação que usam uma BOM ou onde a BOM é usada como uma assinatura UTF-8. . Consulte a subseção “Byte Order Mark” na Seção 16.8, Especiais , para obter mais informações.

Martin Cote
fonte
114
Pode não ser recomendado, mas pela minha experiência em conversões em hebraico, a BOM às vezes é crucial para o reconhecimento UTF-8 no Excel e pode fazer a diferença entre Jibrish e Hebraico
Matanya
26
Pode não ser recomendado, mas fez maravilhas para o meu script PowerShell ao tentar output "æøå"
Marius
63
Independentemente de não ser recomendado pelo padrão, é permitido, e eu prefiro ter algo para agir como uma assinatura UTF-8, e não como alternativas de suposição ou suposição. O software compatível com Unicode deve / deve ser capaz de lidar com sua presença, portanto, eu pessoalmente incentivo seu uso.
martineau
30
@ bames53: Sim, em um mundo ideal, armazenar a codificação de arquivos de texto como metadados do sistema de arquivos seria a melhor maneira de preservá-lo. Mas a maioria de nós que vive no mundo real não pode alterar o sistema de arquivos dos sistemas operacionais em que nossos programas são executados - portanto, usar a assinatura de BOM independente da plataforma do padrão Unicode parece o melhor e mais prático IMHO alternativo.
22614 martineau
34
Ontem, encontrei um arquivo com uma lista técnica UTF-8 que não era UTF-8 (era CP936). O que é lamentável é que os responsáveis ​​pela imensa quantidade de dor causada pela UTF-8 BOM não se dão conta disso.
bames53
243

As outras excelentes respostas já responderam que:

  • Não há diferença oficial entre UTF-8 e BOM-ed UTF-8
  • Uma sequência UTF-8 editada pela BOM começará com os três bytes seguintes. EF BB BF
  • Esses bytes, se presentes, devem ser ignorados ao extrair a sequência do arquivo / fluxo.

Mas, como informações adicionais, a BOM para UTF-8 pode ser uma boa maneira de "cheirar" se uma string foi codificada em UTF-8 ... Ou pode ser uma string legítima em qualquer outra codificação ...

Por exemplo, os dados [EF BB BF 41 42 43] podem ser:

  • A legítima sequência ISO-8859-1 "ï» ¿ABC "
  • A legítima string UTF-8 "ABC"

Portanto, embora seja legal reconhecer a codificação de um conteúdo de arquivo observando os primeiros bytes, você não deve confiar nisso, como mostra o exemplo acima

As codificações devem ser conhecidas, não adivinhadas.

paercebal
fonte
60
@ Alcott: Você entendeu corretamente. A string [EF BB BF 41 42 43] é apenas um monte de bytes. Você precisa de informações externas para escolher como interpretá-las. Se você acredita que esses bytes foram codificados usando a ISO-8859-1, a sequência é "ï» ¿ABC ". Se você acredita que esses bytes foram codificados usando UTF-8, então é "ABC". Se você não sabe, deve tentar descobrir. A lista técnica pode ser uma pista. A ausência de caractere inválido quando decodificado como UTF-8 pode ser outro ... No final, a menos que você possa memorizar / encontrar a codificação de alguma forma, uma matriz de bytes é apenas uma matriz de bytes.
paercebal
19
@paercebal Enquanto "ï» ¿"é válido em latin-1, é muito improvável que um arquivo de texto comece com essa combinação. O mesmo vale para os marcadores ucs2-le / be ÿþ e þÿ. Além disso, você nunca pode saber.
user877329
16
@ deceze Provavelmente é linguisticamente inválido: primeiro ï (o que está ok), depois algumas aspas sem espaço no meio (não o ok). ¿Indica que é espanhol, mas ï não é usado em espanhol. Conclusão: não é latin-1 com uma certeza bem acima da certeza sem ela.
user877329
20
@ usuário Claro, isso não faz necessariamente sentido. Mas se o seu sistema depende de adivinhações , é aí que entram as incertezas. Algum usuário mal-intencionado envia um texto que começa com essas três letras de propósito e, de repente, seu sistema assume que está olhando para o UTF-8 com uma BOM, trata o texto como UTF-8, onde ele deve usar o Latin-1 e ocorre alguma injeção de Unicode. Apenas um exemplo hipotético, mas certamente possível. Você não pode julgar uma codificação de texto por seu conteúdo, ponto final.
deceze
40
"As codificações devem ser conhecidas, não adivinhadas." O coração e a alma do problema. +1, bom senhor. Em outras palavras: padronize seu conteúdo e diga: "Estamos sempre usando essa codificação. Ponto final. Escreva dessa maneira. Leia dessa maneira" ou desenvolva um formato estendido que permita armazenar a codificação como metadados. (Este último, provavelmente precisa de algum "inicialização de codificação padrão", também como dizendo. "A parte que lhe diz a codificação é sempre ASCII.")
jpmc26
135

Há pelo menos três problemas ao colocar uma BOM em arquivos codificados em UTF-8.

  1. Os arquivos que não contêm texto não estão mais vazios porque sempre contêm a BOM.
  2. Os arquivos que contêm texto que está dentro do subconjunto ASCII do UTF-8 não são mais eles mesmos ASCII porque a BOM não é ASCII, o que faz com que algumas ferramentas existentes sejam quebradas e pode ser impossível para os usuários substituir essas ferramentas herdadas.
  3. Não é possível concatenar vários arquivos juntos, porque cada arquivo agora possui uma lista técnica no início.

E, como outros já mencionaram, não é suficiente nem necessário ter uma lista técnica para detectar que algo é UTF-8:

  • Não é suficiente porque uma sequência de bytes arbitrária pode começar com a sequência exata que constitui a BOM.
  • Não é necessário porque você pode apenas ler os bytes como se fossem UTF-8; se for bem-sucedido, é, por definição, UTF-8 válido.
JP
fonte
8
O ponto 1 "Os arquivos que não contêm texto não estão mais vazios porque sempre contêm a BOM", isso (1) confunde o nível do sistema de arquivos do SO com o nível de conteúdo interpretado, além disso (2) assume incorretamente que o uso da BOM deve colocar um BOM também em todos os arquivos vazios. A solução prática para (1) é não fazer (2). Essencialmente, a reclamação se reduz a "é possível colocar uma lista técnica de maneira impraticável em um arquivo vazio, evitando assim a detecção mais fácil de arquivos logicamente vazios (verificando o tamanho do arquivo)". Um bom software ainda deve ser capaz de lidar com isso, pois tem um objetivo.
Saúde e hth. # 1
7
No ponto 2, "Os arquivos que contêm texto ASCII não são mais eles mesmos ASCII", isso confunde ASCII com UTF-8. Um arquivo UTF-8 que contém texto ASCII não é ASCII, é UTF-8. Da mesma forma, um arquivo UTF-16 que contém texto ASCII não é ASCII, é UTF-16. E assim por diante. ASCII é um código de byte único de 7 bits. UTF-8 é uma extensão de comprimento variável de 8 bits do ASCII. Se as "ferramentas quebrarem" devido a> 127 valores, elas simplesmente não são adequadas para um mundo de 8 bits. Uma solução prática simples é usar apenas arquivos ASCII com ferramentas que quebram para valores de bytes não ASCII. Uma solução provavelmente melhor é abandonar essas ferramentas desagradáveis.
Saúde e hth. - Alf
8
No ponto 3, "Não é possível concatenar vários arquivos juntos, porque cada arquivo agora possui uma lista técnica no início" está errado. Não tenho problema em concatenar arquivos UTF-8 com a BOM, portanto é claramente possível. Eu acho que talvez você quisesse dizer que a terra Unix catnão lhe dará um resultado limpo , um resultado que só tem BOM no começo. Se você quis dizer isso, é porque catfunciona no nível de bytes, não no nível de conteúdo interpretado e, de maneira semelhante, catnão pode lidar com fotografias, por exemplo. Ainda assim, não faz muito mal. Isso ocorre porque a BOM codifica um espaço sem quebra de largura zero.
Saúde e hth. #
20
@ Cheersandhth.-Alf Esta resposta está correta. Você está apenas apontando os erros da Microsoft.
Tchrist #
9
@brighty: A situação não melhorou com a adição de um bom.
Deduplicator
84

Aqui estão exemplos do uso da lista técnica que realmente causam problemas reais e, no entanto, muitas pessoas não sabem disso.

BOM quebra scripts

Scripts de shell, scripts Perl, scripts Python, scripts Ruby, scripts Node.js ou qualquer outro executável que precise ser executado por um intérprete - todos começam com uma linha shebang que se parece com uma dessas:

#!/bin/sh
#!/usr/bin/python
#!/usr/local/bin/perl
#!/usr/bin/env node

Ele informa ao sistema qual intérprete precisa ser executado ao chamar esse script. Se o script estiver codificado em UTF-8, pode-se tentar incluir uma lista técnica no início. Mas na verdade o "#!" caracteres não são apenas caracteres. Na verdade, eles são um número mágico que é composto de dois caracteres ASCII. Se você colocar algo (como uma BOM) antes desses caracteres, o arquivo parecerá ter um número mágico diferente e isso pode causar problemas.

Veja Wikipedia, artigo: Shebang, seção: Número mágico :

Os caracteres shebang são representados pelos mesmos dois bytes em codificações ASCII estendidas, incluindo UTF-8, que é comumente usado para scripts e outros arquivos de texto nos sistemas atuais do tipo Unix. No entanto, os arquivos UTF-8 podem começar com a marca de ordem de bytes opcional (BOM); se a função "exec" detectar especificamente os bytes 0x23 e 0x21, a presença da BOM (0xEF 0xBB 0xBF) antes do shebang impedirá a execução do interpretador de scripts.Algumas autoridades recomendam não usar a marca de ordem de bytes nos scripts POSIX (tipo Unix), [14] por esse motivo e por questões de interoperabilidade e questões filosóficas mais amplas. Além disso, uma marca de ordem de bytes não é necessária no UTF-8, pois a codificação não apresenta problemas de endianidade; serve apenas para identificar a codificação como UTF-8. [enfase adicionada]

BOM é ilegal no JSON

Veja RFC 7159, Seção 8.1 :

Implementações não devem adicionar uma marca de ordem de bytes para o início de um texto JSON.

BOM é redundante em JSON

Além de ser ilegal no JSON, também não é necessário determinar a codificação de caracteres, pois existem maneiras mais confiáveis ​​de determinar sem ambiguidade a codificação e a endianidade de caracteres usadas em qualquer fluxo JSON (consulte esta resposta para obter detalhes).

BOM interrompe analisadores JSON

Não é apenas ilegal em JSON e não é necessário , como também quebra todos os softwares que determinam a codificação usando o método apresentado na RFC 4627 :

Determinando a codificação e endianness do JSON, examinando os quatro primeiros bytes para o byte NUL:

00 00 00 xx - UTF-32BE
00 xx 00 xx - UTF-16BE
xx 00 00 00 - UTF-32LE
xx 00 xx 00 - UTF-16LE
xx xx xx xx - UTF-8

Agora, se o arquivo começar com a BOM, ele ficará assim:

00 00 FE FF - UTF-32BE
FE FF 00 xx - UTF-16BE
FF FE 00 00 - UTF-32LE
FF FE xx 00 - UTF-16LE
EF BB BF xx - UTF-8

Observe que:

  1. O UTF-32BE não inicia com três NULs, portanto não será reconhecido
  2. UTF-32LE, o primeiro byte não é seguido por três NULs, portanto, não será reconhecido
  3. UTF-16BE possui apenas um NUL nos quatro primeiros bytes, portanto, não será reconhecido
  4. UTF-16LE possui apenas um NUL nos primeiros quatro bytes, portanto, não será reconhecido

Dependendo da implementação, todos eles podem ser interpretados incorretamente como UTF-8 e, em seguida, mal interpretados ou rejeitados como UTF-8 inválido ou não reconhecidos.

Além disso, se a implementação testar JSON válido, como eu recomendo, ela rejeitará mesmo a entrada que é realmente codificada como UTF-8, porque não inicia com um caractere ASCII <128, como deveria, de acordo com a RFC.

Outros formatos de dados

A lista técnica no JSON não é necessária, é ilegal e interrompe o software que funciona corretamente de acordo com a RFC. Deve ser um exagero simplesmente não usá-lo e, no entanto, sempre há pessoas que insistem em quebrar o JSON usando BOMs, comentários, regras de cotação diferentes ou tipos de dados diferentes. É claro que qualquer pessoa é livre para usar coisas como BOMs ou qualquer outra coisa, se você precisar - apenas não chame isso de JSON.

Para outros formatos de dados que não o JSON, veja como ele realmente se parece. Se as únicas codificações são UTF- * e o primeiro caractere deve ser um caractere ASCII menor que 128, você já possui todas as informações necessárias para determinar a codificação e a endianidade de seus dados. A adição de listas técnicas, mesmo como um recurso opcional, apenas o tornaria mais complicado e propenso a erros.

Outros usos da lista técnica

Quanto aos usos fora do JSON ou scripts, acho que já existem respostas muito boas aqui. Eu queria adicionar informações mais detalhadas especificamente sobre scripts e serialização, porque é um exemplo de caracteres da BOM causando problemas reais.

rsp
fonte
5
O rfc7159, que substitui o rfc4627, na verdade sugere que o suporte à BOM pode não ser tão ruim. Basicamente, não ter uma lista técnica é apenas um argumento ambíguo, para que o software antigo do Windows e Unix que não é compatível com Unicode ainda possa processar o utf-8.
Eric Grange
2
Parece que o JSON precisa ser atualizado para suportá-lo, o mesmo com scripts Perl, scripts Python, scripts Ruby, Node.js. Só porque essas plataformas optaram por não incluir suporte, isso não elimina necessariamente o uso da BOM. A Apple vem tentando matar a Adobe há alguns anos, e a Adobe ainda está por aí. Mas um post esclarecedor.
Htm11h
13
@EricGrange, você parece estar apoiando muito a BOM, mas falha ao perceber que isso tornaria o formato de "texto sem formatação" onipresente, universalmente útil e ideal ótimo mínimo , uma relíquia do passado anterior à UTF8! Adicionar qualquer tipo de cabeçalho (dentro da banda) ao fluxo de texto sem formatação imporia um protocolo obrigatório aos arquivos de texto mais simples, tornando-o nunca mais o "mais simples"! E para que ganho? Para suportar todas as outras codificações CP antigas que também não tinham assinaturas, você pode confundi-las com UTF-8? (BTW, ASCII também é UTF-8. Então, uma lista técnica para eles também?;) Vamos lá.)
Sz.
2
Esta resposta é a razão pela qual cheguei a esta pergunta! Eu crio meus scripts bash no Windows e encontro muitos problemas ao publicar esses scripts no Linux! A mesma coisa com os arquivos jason.
Tono Nam
2
Eu gostaria de poder votar esta resposta cerca de cinquenta vezes. Também quero acrescentar que, neste ponto, o UTF-8 venceu a guerra dos padrões e quase todo o texto produzido na Internet é UTF-8. Algumas das linguagens de programação mais populares (como C # e Java) usam UTF-16 internamente, mas quando os programadores usam essas linguagens gravam arquivos nos fluxos de saída, eles quase sempre os codificam como UTF-8. Portanto, não faz mais sentido ter uma lista técnica para marcar um arquivo UTF-8; UTF-8 deve ser o padrão usado ao ler e tente apenas outras codificações se a decodificação UTF-8 falhar.
Rmunn 23/08/19
51

O que há de diferente entre UTF-8 e UTF-8 sem BOM?

Resposta curta: No UTF-8, uma BOM é codificada como os bytes EF BB BFno início do arquivo.

Resposta longa:

Originalmente, esperava-se que o Unicode fosse codificado em UTF-16 / UCS-2. A lista técnica foi projetada para este formulário de codificação. Quando você possui unidades de código de 2 bytes, é necessário indicar em qual ordem esses dois bytes estão, e uma convenção comum para isso é incluir o caractere U + FEFF como uma "Marca de Ordem de Byte" no início dos dados. O caractere U + FFFE é permanentemente não atribuído, para que sua presença possa ser usada para detectar a ordem de bytes incorreta.

O UTF-8 tem a mesma ordem de bytes, independentemente da disponibilidade da plataforma, portanto, uma marca de ordem de bytes não é necessária. No entanto, pode ocorrer (como a sequência de bytes EF BB FF) nos dados que foram convertidos em UTF-8 a partir de UTF-16 ou como uma "assinatura" para indicar que os dados são UTF-8.

Qual é melhor?

Sem. Como Martin Cote respondeu, o padrão Unicode não o recomenda. Causa problemas com software não compatível com BOM.

Uma maneira melhor de detectar se um arquivo é UTF-8 é executar uma verificação de validade. O UTF-8 possui regras estritas sobre quais seqüências de bytes são válidas, portanto, a probabilidade de um falso positivo é desprezível. Se uma sequência de bytes se parece com UTF-8, provavelmente é.

dan04
fonte
8
isso também invalidaria o UTF-8 válido com um único byte incorreto, no entanto: /
endolith
8
-1 re "Causa problemas com software não compatível com BOM.", Isso nunca foi um problema para mim, mas, pelo contrário, essa ausência de BOM causa problemas com software compatível com BOM (em particular o Visual C ++). problema. Portanto, essa afirmação é muito específica da plataforma , um ponto de vista estreito do Unix-land, mas é apresentada de forma enganosa como se fosse aplicada em geral. O que não acontece.
Saúde e hth. # 1
6
Não, o UTF-8 não possui BOM. Esta resposta está incorreta. Veja o padrão Unicode.
Tchrist #
2
Você pode até pensar que possui um arquivo ASCII puro ao apenas olhar para os bytes. Mas esse poderia ser um arquivo utf-16, onde você teria que procurar palavras e não bytes. O software moderno deve estar ciente das listas técnicas. A leitura do utf-8 ainda pode falhar se detectar sequências inválidas, pontos de código que podem usar uma sequência menor ou pontos de código que são substitutos. Para utf-16, a leitura também pode falhar quando houver substitutos órfãos.
Brighty
1
@Alf, eu discordo de sua interpretação de uma atitude que não seja da BOM como " específica da plataforma , um ponto de vista estreito do Unix-land". Para mim, a única maneira pela qual a mente estreita poderia estar na "terra Unix" seria se o MS e o Visual C ++ viessem antes do * NIX, o que não aconteceu. O fato de que MS (eu assumo conscientemente) começou a usar um BOM no UTF-8 em vez de UTF-16 sugere-me que eles promoveram quebra sh, perl, g++, e muitas outras ferramentas livres e poderosos. Quer que as coisas funcionem? Basta comprar as versões do MS. A Microsoft criou o problema específico da plataforma, assim como o desastre de seu intervalo \ x80- \ x95.
bballdave025 17/01
30

UTF-8 com lista técnica é melhor identificado. Cheguei a essa conclusão da maneira mais difícil. Estou trabalhando em um projeto em que um dos resultados é um arquivo CSV , incluindo caracteres Unicode.

Se o arquivo CSV for salvo sem uma BOM, o Excel considerará ANSI e mostrará sem sentido. Depois de adicionar "EF BB BF" à frente (por exemplo, salvando-o novamente usando o Bloco de Notas com UTF-8; ou Notepad ++ com UTF-8 com BOM), o Excel abre bem.

A pré-adição do caractere BOM aos arquivos de texto Unicode é recomendada pela RFC 3629: "UTF-8, um formato de transformação ISO 10646", novembro de 2003 em http://tools.ietf.org/html/rfc3629 (esta última informação foi encontrada em: http://www.herongyang.com/Unicode/Notepad-Byte-Order-Mark-BOM-FEFF-EFBBBF.html )

Helen Craigman
fonte
6
Obrigado por esta excelente dica, caso alguém esteja criando arquivos UTF-8 para serem usados ​​pelo Excel. Em outras circunstâncias, eu continuaria a seguir as outras respostas e pular a lista técnica.
Barfuin #
5
Também é útil se você criar arquivos que contenham apenas ASCII e, posteriormente, tiverem adicionado não-ascii. Acabei de encontrar um problema: software que espera utf8, cria arquivo com alguns dados para edição do usuário. Se o arquivo inicial contiver apenas ASCII, for aberto em alguns editores e depois salvo, ele terminará em latin-1 e tudo será interrompido. Se eu adicionar a BOM, ela será detectada como UTF8 pelo editor e tudo funcionará.
Roberto Alsina
1
Encontrei várias ferramentas relacionadas à programação que exigem que a BOM reconheça corretamente os arquivos UTF-8 corretamente. Visual Studio, SSMS, SoureTree ....
kjbartel
5
Onde você lê uma recomendação para usar uma lista técnica nessa RFC? No máximo, há uma forte recomendação de não proibi-lo sob certas circunstâncias em que isso é difícil.
Deduplicator
8
O Excel pensa que é ANSI e mostra sem sentido, então o problema está no Excel.
Isaac
17

A lista técnica tende a crescer (sem trocadilhos (sic)) em algum lugar e lugar. E quando cresce (por exemplo, não é reconhecido por navegadores, editores etc.), aparece como os caracteres estranhos no início do documento (por exemplo, arquivo HTML, resposta JSON , RSS , etc.) e causa constrangimentos, como o recente problema de codificação ocorrido durante a conversa de Obama no Twitter .

É muito irritante quando aparece em locais difíceis de depurar ou quando o teste é negligenciado. Portanto, é melhor evitá-lo, a menos que você precise usá-lo.

Halil Özgür
fonte
Sim, apenas passei horas identificando um problema causado por um arquivo sendo codificado como UTF-8 em vez de UTF-8 sem BOM. (O problema só apareceu no IE7, o que me levou a uma
loucura
Leitores futuros: observe que a questão do tweet que mencionei acima não estava estritamente relacionada à BOM, mas, se fosse, o tweet seria distorcido de maneira semelhante, mas no início do tweet.
Halil Özgür
12
@ user984003 Não, o problema é que a Microsoft enganou você. O que chama UTF-8 não é UTF-8. O que chama UTF-8 sem BOM é o que realmente é UTF-8.
Tchrist
o que o "sic" adiciona ao seu "sem trocadilhos"
JoelFan
2
@JoelFan não me lembro mais, mas eu acho que o trocadilho pode ter sido destinado apesar da afirmação do autor :)
Halil Özgür
17

Pergunta: O que há de diferente entre UTF-8 e UTF-8 sem uma lista técnica? Qual é melhor?

Aqui estão alguns trechos do artigo da Wikipedia sobre a marca de ordem de bytes (BOM) que acredito oferecer uma resposta sólida a essa pergunta.

Sobre o significado da BOM e UTF-8:

O padrão Unicode permite a lista técnica no UTF-8 , mas não requer ou recomenda seu uso. A ordem dos bytes não tem significado no UTF-8, portanto, seu único uso no UTF-8 é sinalizar no início que o fluxo de texto está codificado no UTF-8.

Argumento para NÃO usar uma lista técnica:

A principal motivação para não usar uma lista técnica é a compatibilidade com versões anteriores de software que não reconhece Unicode ... Outra motivação para não usar uma lista técnica é incentivar o UTF-8 como a codificação "padrão".

Argumento PARA usando uma BOM:

O argumento para usar uma lista técnica é que, sem ela, é necessária uma análise heurística para determinar qual caractere de codificação um arquivo está usando. Historicamente, essa análise, para distinguir várias codificações de 8 bits, é complicada, propensa a erros e, às vezes, lenta. Diversas bibliotecas estão disponíveis para facilitar a tarefa, como o Mozilla Universal Charset Detector e International Components for Unicode.

Os programadores assumem erroneamente que a detecção de UTF-8 é igualmente difícil (não é porque a grande maioria das seqüências de bytes é UTF-8 inválida, enquanto as codificações que essas bibliotecas estão tentando distinguir permitem todas as seqüências de bytes possíveis). Portanto, nem todos os programas compatíveis com Unicode executam essa análise e, em vez disso, confiam na BOM.

Em particular, compiladores e intérpretes da Microsoft , e muitos softwares no Microsoft Windows, como o Bloco de Notas, não leem corretamente o texto UTF-8, a menos que possuam apenas caracteres ASCII ou iniciem na BOM e adicionam uma BOM ao início ao salvar texto como UTF-8. O Google Docs adicionará uma lista técnica quando um documento do Microsoft Word for baixado como um arquivo de texto sem formatação.

Em que é melhor, COM ou SEM A BOM:

A IETF recomenda que, se um protocolo (a) sempre usa UTF-8, ou (b) tem alguma outra maneira de indicar qual codificação está sendo usada, então "DEVE proibir o uso de U + FEFF como assinatura".

Minha conclusão:

Use a lista técnica apenas se a compatibilidade com um aplicativo de software for absolutamente essencial.

Observe também que, embora o artigo mencionado na Wikipedia indique que muitos aplicativos da Microsoft dependem da BOM para detectar corretamente o UTF-8, esse não é o caso de todos os aplicativos da Microsoft. Por exemplo, conforme indicado por @barlop , ao usar o prompt de comando do Windows com UTF-8 , comandos como esse typee morenão esperam que a lista técnica esteja presente. Se a lista técnica estiver presente, ela poderá ser problemática, assim como para outros aplicativos.


† O chcpcomando oferece suporte para UTF-8 ( sem a BOM) através da página de códigos 65001 .

DavidRR
fonte
5
É melhor me estressar SEM A BOM . Descobri que .htaccesse gzip compressionem combinação com UTF-8 BOM dá um erro de codificação Mudança para codificação em UTF-8 sem BOM seguimento a uma sugestão como explicado aqui resolver os problemas
Chetabahana
1
'Outra motivação para não usar uma lista técnica é incentivar o UTF-8 como a codificação "padrão".' - Que argumento é tão forte e válido que você realmente pode ter parado a resposta! ...; -o A menos que você tenha uma idéia melhor para a representação universal de texto, isso é. ;) (Não sei quantos anos você tem, quantos anos teve que sofrer na era anterior à UTF8 (quando os linguistas consideravam desesperadamente mudar seus alfabetos), mas posso lhe dizer que a cada segundo nos aproximamos da libertação a bagunça de todas as antigas codificações de byte único sem metadados, em vez de ter "o único" é pura alegria.)
Sz.
Consulte também este comentário sobre como adicionar uma BOM (ou qualquer outra coisa!) Ao formato de arquivo de texto mais simples, "texto sem formatação", significaria impedir que exatamente o melhor formato de codificação de texto universal fosse "sem formatação" e "simples" (por exemplo, "overheadless")! ...
Sz.
A BOM é principalmente problemática no Linux, porque muitos utilitários realmente não suportam Unicode (eles truncam alegremente no meio dos pontos de código, por exemplo). Para a maioria dos outros ambientes de software modernos, use a BOM sempre que a codificação não for ambígua (por meio de especificações ou metadados).
Eric Grange
9

Essa pergunta já tem um milhão e uma de respostas e muitas delas são muito boas, mas eu queria tentar esclarecer quando uma BOM deve ou não ser usada.

Como mencionado, qualquer uso da UTF BOM (Byte Order Mark) para determinar se uma string é UTF-8 ou não é uma adivinhação. Se houver metadados adequados disponíveis (como charset="utf-8"), você já sabe o que deve usar, mas, caso contrário, precisará testar e fazer algumas suposições. Isso envolve verificar se o arquivo de uma sequência começa com o código de bytes hexadecimais, EF BB BF.

Se for encontrado um código de bytes correspondente à BOM UTF-8, a probabilidade é alta o suficiente para assumir que é UTF-8 e você poderá prosseguir a partir daí. Quando forçado a fazer esse palpite, no entanto, uma verificação de erro adicional durante a leitura ainda seria uma boa idéia, caso algo ocorra. Você só deve assumir que uma lista técnica não é UTF-8 (por exemplo, latin-1 ou ANSI) se a entrada definitivamente não deve ser UTF-8 com base em sua origem. Se não houver BOM, no entanto, você pode simplesmente determinar se deve ser UTF-8 validando com a codificação.

Por que uma lista técnica não é recomendada?

  1. O software que não reconhece Unicode ou é pouco compatível pode assumir que é latin-1 ou ANSI e não tira a lista técnica da string, o que obviamente pode causar problemas.
  2. Não é realmente necessário (verifique se o conteúdo é compatível e sempre use UTF-8 como substituto quando nenhuma codificação compatível for encontrada)

Quando você deve codificar com uma lista técnica?

Se não conseguir gravar os metadados de nenhuma outra maneira (por meio de uma tag charset ou meta do sistema de arquivos) e os programas usados ​​como BOMs, você deve codificar com uma BOM. Isso é especialmente verdade no Windows, onde geralmente se supõe que qualquer coisa sem uma lista técnica esteja usando uma página de código herdada. A lista técnica informa a programas como o Office que, sim, o texto desse arquivo é Unicode; aqui está a codificação usada.

Quando se trata disso, os únicos arquivos com os quais realmente tenho problemas são o CSV. Dependendo do programa, ele deve ou não deve ter uma lista técnica. Por exemplo, se você estiver usando o Excel 2007+ no Windows, ele deverá ser codificado com uma BOM se você deseja abri-lo sem problemas e não precisar recorrer à importação dos dados.

jpc-ae
fonte
2
A última seção da sua resposta está 100% correta: o único motivo para usar uma BOM é quando você precisa interoperar com um software de buggy que não usa UTF-8 como padrão para analisar arquivos desconhecidos.
rmunn
8

Note-se que, para alguns arquivos, você não deve ter a lista técnica nem no Windows. Exemplos são SQL*plusou VBScriptarquivos. Caso esses arquivos contenham uma lista técnica, você receberá um erro ao tentar executá-los.

Wernfried Domscheit
fonte
8

O UTF-8 com BOM só ajuda se o arquivo realmente contém alguns caracteres não ASCII. Se ele estiver incluído e não houver nenhum, poderá interromper aplicativos mais antigos que, de outra forma, teriam interpretado o arquivo como ASCII simples. Esses aplicativos definitivamente falharão quando encontrarem um caractere não ASCII, portanto, na minha opinião, a lista técnica só deve ser adicionada quando o arquivo puder e não puder mais ser interpretado como ASCII simples.

Quero deixar claro que prefiro não ter a lista técnica. Adicione-o se algum lixo antigo quebrar sem ele e a substituição desse aplicativo herdado não for viável.

Não faça nada esperar uma BOM para UTF-8.

James Wakefield
fonte
7

Citado na parte inferior da página da Wikipedia na BOM: http://en.wikipedia.org/wiki/Byte-order_mark#cite_note-2

"O uso de uma BOM não é necessário nem recomendado para UTF-8, mas pode ser encontrado em contextos em que os dados UTF-8 são convertidos de outros formulários de codificação que usam uma BOM ou onde a BOM é usada como uma assinatura UTF-8"

pib
fonte
2
Você tem algum exemplo em que o software decide se deve usar UTF-8 com / sem BOM, com base no fato de a codificação anterior da qual ela está codificando, tenha uma BOM ou não ?! Isso parece uma afirmação absurda
barlop
7

UTF-8 sem BOM não possui BOM, o que não o torna melhor que UTF-8 com BOM, exceto quando o consumidor do arquivo precisa saber (ou se beneficiaria de saber) se o arquivo é codificado em UTF-8 ou não.

A lista técnica geralmente é útil para determinar a resistência da codificação, o que não é necessário para a maioria dos casos de uso.

Além disso, a lista técnica pode ser um ruído / dor desnecessário para os consumidores que não conhecem ou se importam com isso e pode resultar em confusão do usuário.

Romain
fonte
2
"que não tem utilidade para UTF-8, já que é de 8 bits por glifo." Er ... não, apenas os glifos ASCII-7 têm 8 bits em UTF-8. Qualquer coisa além disso será de 16, 24 ou 32 bits.
Powerlord 8/02/10
3
"A lista técnica geralmente é útil para determinar a resistência da codificação, o que não é necessário para a maioria dos casos de uso." ... a resistência simplesmente não se aplica ao UTF-8, independentemente do caso de uso
JoelFan
6

Eu olho para isso de uma perspectiva diferente. Eu acho que UTF-8 com BOM é melhor , pois fornece mais informações sobre o arquivo. Só uso o UTF-8 sem BOM se tiver problemas.

Estou usando vários idiomas (mesmo cirílico ) em minhas páginas por um longo tempo e, quando os arquivos são salvos sem a BOM e os abro novamente para edição com um editor (como o cherouvim também observou), alguns caracteres estão corrompidos.

Observe que o Bloco de notas clássico do Windows salva automaticamente os arquivos com uma BOM quando você tenta salvar um arquivo recém-criado com a codificação UTF-8.

Pessoalmente, salvei arquivos de script do lado do servidor (.asp, .ini, .aspx) com arquivos BOM e .html sem BOM .

user1358065
fonte
4
Obrigado pela excelente dica sobre o Windows Classic Notepad. Eu já passei algum tempo descobrindo exatamente a mesma coisa. Minha consequência foi sempre usar o Notepad ++ em vez do bloco de notas clássico do Windows. :-)
barfuin
É melhor você usar madedit. É o único editor que - no modo hexadecimal - mostra um caractere se você selecionar uma sequência utf-8 bytes em vez de uma base 1: 1 entre byte e caractere. Um editor hexadecimal que esteja ciente de um arquivo UTF-8 deve ter o mesmo efeito que o madedit!
Brighty
@brighty Eu não acho que você precise de um para um por causa da lista técnica. não importa, não é preciso muito para reconhecer que uma lista técnica utf-8 é efbbbf ou fffe (de fffe, se lida incorretamente). Pode-se simplesmente excluir esses bytes. Não é ruim apesar de ter um mapeamento para o resto do arquivo, porém, mas também ser capaz de byte de exclusão por byte demasiado
barlop
@barlop Por que você deseja excluir uma lista técnica utf-8 se o conteúdo do arquivo é codificado em utf-8? A lista técnica é reconhecida pelos modernos visualizadores de texto, controles de texto e editores de texto. Uma visualização individual de uma sequência utf-8 não faz sentido, já que n bytes resultam em um caractere. É claro que um editor de texto ou hexadecimal deve permitir excluir qualquer byte, mas isso pode levar a seqüências utf-8 inválidas.
Brighty
@brighty utf-8 com bom é uma codificação, e utf-8 sem bom é uma codificação. O prompt do cmd usa utf8 sem bom .. portanto, se você possui um arquivo utf8, executa o comando chcp 65001para suporte ao utf8, é utf8 sem bom. Se você fizer type myfileisso, apenas será exibido corretamente se não houver bom. Se você fizer echo aaa>a.aou echo אאא>a.a enviar os caracteres para o arquivo aa e tiver o chcp 65001, ele será exibido sem BOM.
barlop
6

Quando você deseja exibir informações codificadas em UTF-8, pode não ter problemas. Declare, por exemplo, um documento HTML como UTF-8 e você terá tudo exibido no seu navegador que está contido no corpo do documento.

Mas esse não é o caso quando temos arquivos de texto, CSV e XML, no Windows ou Linux.

Por exemplo, um arquivo de texto no Windows ou Linux, uma das coisas mais fáceis que se possa imaginar, não é (geralmente) UTF-8.

Salve-o como XML e declare-o como UTF-8:

<?xml version="1.0" encoding="UTF-8"?>

Ele não será exibido (não será lido) corretamente, mesmo se declarado como UTF-8.

Eu tinha uma série de dados contendo letras francesas, que precisavam ser salvas como XML para organização. Sem criar um arquivo UTF-8 desde o início (alterando opções no IDE e "Criar novo arquivo") ou adicionar a lista técnica no início do arquivo

$file="\xEF\xBB\xBF".$string;

Não pude salvar as letras francesas em um arquivo XML.

Florin Sima
fonte
1
FTM, em XML, acho que você deve manter o arquivo como ASCII e usar entidades .
Alois Mahdal
4
Sei que essa é uma resposta antiga, mas só quero mencionar que está errada. Arquivos de texto no Linux (não podem falar por outros Unixes) geralmente / são / UTF-8.
Functino 14/11/2015
6

Uma diferença prática é que, se você escrever um shell script para o Mac OS X e salvá-lo como simples UTF-8, obterá a resposta:

#!/bin/bash: No such file or directory

em resposta à linha shebang especificando qual shell você deseja usar:

#!/bin/bash

Se você salvar como UTF-8, nenhuma lista técnica (por exemplo, no BBEdit ) ficará bem.

David
fonte
8
Isso ocorre porque a Microsoft trocou o significado do que o padrão diz. O UTF-8 não possui BOM: eles criaram o Microsoft UTF-8, que insere uma BOM espúria na frente do fluxo de dados e, em seguida, informava que não, na verdade, é UTF-8. Não é. É apenas estender e corromper.
Tchrist
4

Como mencionado acima, o UTF-8 com BOM pode causar problemas com o software não compatível com BOM (ou compatível). Certa vez, editei arquivos HTML codificados como UTF-8 + BOM com o KompoZer baseado em Mozilla , pois um cliente exigia que o WYSIWYG programa .

Invariavelmente, o layout seria destruído ao salvar. Levou algum tempo para mexer nisso. Esses arquivos funcionaram bem no Firefox, mas mostraram uma peculiaridade de CSS no Internet Explorer, destruindo o layout novamente. Depois de mexer nos arquivos CSS vinculados por horas sem sucesso, descobri que o Internet Explorer não gostava do arquivo HTML do BOMfed. Nunca mais.

Além disso, eu encontrei isso na Wikipedia:

Os caracteres shebang são representados pelos mesmos dois bytes em codificações ASCII estendidas, incluindo UTF-8, que é comumente usado para scripts e outros arquivos de texto nos sistemas atuais do tipo Unix. No entanto, os arquivos UTF-8 podem começar com a marca de ordem de bytes opcional (BOM); se a função "exec" detectar especificamente os bytes 0x23 0x21, a presença da BOM (0xEF 0xBB 0xBF) antes do shebang impedirá a execução do interpretador de scripts. Algumas autoridades recomendam não usar a marca de ordem de bytes nos scripts POSIX (tipo Unix), [15] por esse motivo e por questões de interoperabilidade e questões filosóficas mais amplas.

Marek Möhling
fonte
4

A FAQ da Marca de pedido de bytes Unicode (BOM) fornece uma resposta concisa:

P: Como devo lidar com listas técnicas?

A: Aqui estão algumas diretrizes a seguir:

  1. Um protocolo específico (por exemplo, convenções da Microsoft para arquivos .txt) pode exigir o uso da BOM em determinados fluxos de dados Unicode, como arquivos. Quando você precisar estar em conformidade com esse protocolo, use uma BOM.

  2. Alguns protocolos permitem listas técnicas opcionais no caso de texto não marcado. Nesses casos,

    • Onde um fluxo de dados de texto é conhecido por texto sem formatação, mas de codificação desconhecida, a BOM pode ser usada como uma assinatura. Se não houver BOM, a codificação pode ser qualquer coisa.

    • Onde se sabe que um fluxo de dados de texto é um texto Unicode simples (mas não qual endian), a BOM pode ser usada como uma assinatura. Se não houver BOM, o texto deve ser interpretado como big endian.

  3. Alguns protocolos orientados a bytes esperam caracteres ASCII no início de um arquivo. Se UTF-8 for usado com esses protocolos, o uso da BOM como assinatura do formulário de codificação deve ser evitado.

  4. Onde o tipo exato do fluxo de dados é conhecido (por exemplo, Unicode big endian ou Unicode little endian), a BOM não deve ser usada. Em particular, sempre que um fluxo de dados é declarado como UTF-16BE, UTF-16LE, UTF-32BE ou UTF-32LE, uma BOM não deve ser usada.

Wernfried Domscheit
fonte
1

Em http://en.wikipedia.org/wiki/Byte-order_mark :

A marca de ordem de bytes (BOM) é um caractere Unicode usado para sinalizar o endianness (ordem de bytes) de um arquivo ou fluxo de texto. Seu ponto de código é U + FEFF. O uso da lista técnica é opcional e, se usado, deve aparecer no início do fluxo de texto. Além de seu uso específico como um indicador de ordem de bytes, o caractere BOM também pode indicar em qual das várias representações Unicode o texto está codificado.

Sempre usar uma BOM no seu arquivo garantirá que ele sempre seja aberto corretamente em um editor que suporte UTF-8 e BOM.

Meu verdadeiro problema com a ausência de BOM é o seguinte. Suponha que tenhamos um arquivo que contenha:

abc

Sem BOM, isso abre como ANSI na maioria dos editores. Portanto, outro usuário deste arquivo o abre e anexa alguns caracteres nativos, por exemplo:

abg-αβγ

Opa ... Agora, o arquivo ainda está em ANSI e adivinhem, "αβγ" não ocupa 6 bytes, mas 3. Este não é o UTF-8 e isso causa outros problemas posteriormente na cadeia de desenvolvimento.

cherouvim
fonte
9
Certifique-se de que bytes espúrios apareçam no início de software que não reconhece BOM. Yay.
Romain
1
@Romain Muller: por exemplo, o PHP 5 lançará erros "impossíveis" quando você tentar enviar cabeçalhos após a BOM.
Piskvor saiu do prédio em
5
αβγ não é ascii, mas pode aparecer em codificações 8bit-ascii-bassed. O uso de uma lista técnica desativa um benafit de utf-8, sua compatibilidade com ascii (capacidade de trabalhar com aplicativos de lagacy nos quais ascii puro é usado).
Ctrl-alt-delor
1
Esta é a resposta errada. Uma string com uma lista técnica à frente é outra coisa completamente diferente. Não deveria estar lá e apenas estraga tudo.
Tchrist
Sem BOM, isso abre como ANSI na maioria dos editores. Eu concordo absolutamente. Se isso acontecer, você terá sorte se lidar com a página de código correta, mas, na verdade, é apenas uma suposição, porque a página de código não faz parte do arquivo. Uma lista técnica é.
Brighty
1

Aqui está minha experiência com as solicitações de recebimento do Visual Studio, Sourcetree e Bitbucket, que têm me causado alguns problemas:

Portanto, a lista técnica com uma assinatura incluirá um caractere de ponto vermelho em cada arquivo ao revisar uma solicitação de recebimento (pode ser bastante irritante).

Digite a descrição da imagem aqui

Se você passar o mouse sobre ele, ele mostrará um caractere como "ufeff", mas o Sourcetree não mostra esses tipos de marcações de byte; portanto, provavelmente terminará nas solicitações pull, o que deve ser aceitável, porque é assim que Visual Studio 2017 codifica novos arquivos agora, então talvez o Bitbucket deva ignorar isso ou fazer com que seja mostrado de outra maneira, mais informações aqui:

Marcador de ponto vermelho BitBucket diff view

Leo
fonte
-4

UTF com uma lista técnica é melhor se você usar UTF-8 em arquivos HTML e se usar cirílico sérvio, latim sérvio, alemão, húngaro ou algum idioma exótico na mesma página.

Essa é a minha opinião (30 anos no setor de computação e TI).

user2173444
fonte
1
Acho que isso também é verdade. Se você usar caracteres fora do primeiro conjunto ASCII 255 e omitir a BOM, os navegadores o interpretarão como ISO-8859-1 e você obterá caracteres ilegíveis. Dadas as respostas acima, aparentemente os fornecedores de navegadores estão fazendo a coisa errada quando não detectam uma lista técnica. Mas, a menos que você trabalhe no Microsoft Edge / Mozilla / Webkit / Blink, não terá outra opção a não ser trabalhar com os defeitos desses aplicativos.
Asontu # 28/17
UTF o que? UTF-8? UTF-16? Algo mais?
Peter Mortensen