it-swarm.dev

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

O que há de diferente entre UTF-8 e UTF-8 sem um BOM ? Qual é melhor?

720
simple

A BOM UTF-8 é uma sequência de Bytes no início de um fluxo de texto (EF BB BF) que permite ao leitor adivinhar um arquivo de forma mais confiável como sendo codificado em UTF-8.

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

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

2.6 Esquemas de Codificação

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

683
Martin Cote

As outras respostas excelentes já responderam que:

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

Mas, como informação adicional para isso, a BOM para UTF-8 poderia ser uma boa maneira de "cheirar" se uma string fosse codificada em UTF-8 ... Ou poderia ser uma string legítima em qualquer outra codificação ...

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

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 divinizadas.

208
paercebal

Existem pelo menos três problemas com a colocação de 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 lista de materiais.
  2. Arquivos que contêm texto que está dentro do subconjunto ASCII de 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 divididas e pode ser impossível para os usuários substituir essas ferramentas legadas.
  3. Não é possível concatenar vários arquivos juntos porque cada arquivo agora tem uma lista de materiais no início.

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

  • Não é suficiente porque uma sequência de bytes arbitrários pode começar com a sequência exata que constitui a lista de materiais.
  • Não é necessário porque você pode apenas ler os bytes como se fossem UTF-8; se isso for bem sucedido, é, por definição, válido UTF-8.
114
J P

É uma pergunta antiga com muitas boas respostas, mas uma coisa deve ser adicionada.

Todas as respostas são muito gerais. O que eu gostaria de acrescentar são exemplos do uso de BOMs que realmente causam problemas reais e muitas pessoas não sabem disso.

BOM quebra scripts

Scripts shell, scripts Perl, scripts Python, scripts Ruby, scripts Node.js ou qualquer outro executável que precise ser executado por um interpretador - todos começam com uma linha Shebang que se parece com um desses:

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

Ele informa ao sistema qual interpretador precisa ser executado ao invocar tal script. Se o script estiver codificado em UTF-8, pode ser tentado incluir uma lista técnica no início. Mas na verdade o "#!" personagens não são apenas personagens. Eles são, na verdade, um número mágico que por acaso é composto de dois caracteresASCII. Se você colocar algo (como uma lista de materiais) 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 estendidas ASCII, incluindo UTF-8, que é comumente usado para scripts e outros arquivos de texto em sistemas atuais do tipo Unix. No entanto, os arquivos UTF-8 podem começar com a marca de ordem de byte opcional (BOM); se a função "exec" detectar especificamente os bytes 0x23 e 0x21, então a presença do BOM (0xEF 0xBB 0xBF) antes do Shebang impedirá que o interpretador de scripts seja executado. Algumas autoridades recomendam contra o uso da marca de ordem de byte em scripts POSIX (Unix-like), [14] por este motivo e para maior interoperabilidade e preocupações filosóficas. Além disso, uma marca de ordem de byte não é necessária em UTF-8, já que a codificação não possui problemas de endianness; serve apenas para identificar a codificação como UTF-8. [enfase adicionada]

BOM é ilegal em JSON

Veja RFC 7159, Seção 8.1 :

Implementações NÃO DEVEM adicionar uma marca de ordem de byte ao início de um texto JSON.

BOM é redundante em JSON

Não só é illegal em JSON, também é não é necessário para determinar a codificação de caracteres porque existem maneiras mais confiáveis ​​de determinar inequivocamente a codificação de caracteres e a endianness usadas em qualquer fluxo JSON (veja esta resposta para detalhes).

BOM divide analisadores JSON

Não só é ilegal em JSON e não é necessário , ele realmente quebra todos os softwares que determinam a codificação usando o método apresentado em RFC 4627 :

Determinando a codificação e o endianness de JSON, examinando os primeiros 4 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 o BOM, 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, por isso não será reconhecido
  2. UTF-32LE o primeiro byte não é seguido por 3 NULs por isso não será reconhecido
  3. UTF-16BE tem apenas 1 NUL nos primeiros 4 bytes, por isso não será reconhecido
  4. UTF-16LE tem apenas 1 NUL nos primeiros 4 bytes, por isso não será reconhecido

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

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

Outros formatos de dados

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

Para outros formatos de dados além do JSON, veja como ele realmente se parece. Se as únicas codificações forem UTF- * e o primeiro caractere tiver que ser um caractere ASCII menor que 128, você já terá todas as informações necessárias para determinar a codificação e o endianness de seus dados. Adicionar BOMs como um recurso opcional só tornaria mais complicado e propenso a erros.

Outros usos do BOM

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 BOM causando problemas reais.

65
rsp

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

Resposta curta: Em UTF-8, uma BOM é codificada como bytes EF BB BF no início do arquivo.

Resposta longa:

Originalmente, era esperado que Unicode fosse codificado em UTF-16/UCS-2. A lista de materiais foi projetada para este formulário de codificação. Quando você tem unidades de código de 2 bytes, é necessário indicar em que ordem esses dois bytes estão, e uma convenção comum para isso é incluir o caractere U + FEFF como "Byte Order Mark" 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 errada de byte.

O UTF-8 tem a mesma ordem de byte, independentemente do endianness da plataforma, portanto, uma marca de ordem de byte não é necessária. No entanto, pode ocorrer (como a seqüência de bytes EF BB FF) em dados que foi convertido em UTF-8 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 recomenda isso. Isso causa problemas com software sem reconhecimento de BOM.

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

48
dan04

UTF-8 com BOM é melhor identificado. Cheguei a essa conclusão da maneira mais difícil. Eu estou trabalhando em um projeto onde um dos resultados é um arquivo CSV , incluindo caracteres Unicode.

Se o arquivo CSV for salvo sem um BOM, o Excel considerará o ANSI e exibirá conteúdo sem sentido. Depois de adicionar "EF BB BF" na frente (por exemplo, salvando-o novamente usando o Bloco de notas com UTF-8; ou o 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 de ISO 10646", novembro de 2003 em http://tools.ietf.org/html/rfc3629 (este último informação encontrada em: http://www.herongyang.com/Unicode/Notepad-Byte-Order-Mark-BOM-FEFF-EFBBBF.html )

29
Helen Craigman

BOM tende a crescer (sem trocadilhos (sic)) em algum lugar, em algum lugar. E quando ele explode (por exemplo, não é reconhecido por navegadores, editores, etc.), ele aparece como caracteres estranhos  no início do documento (por exemplo, arquivo HTML, JSON resposta, RSS , etc.) e provoca o tipo de constrangimentos como o problema de codificação recente experimentado durante a conversa de Obama no Twitter .

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

17
Halil Özgür

Pergunta:O que há de diferente entre UTF-8 e UTF-8 sem um BOM? Qual é o melhor?

Aqui estão alguns trechos do artigo da Wikipédia sobre a byte order mark (BOM) que, acredito, oferecem uma resposta sólida para essa questão.

Sobre o significado do BOM e UTF-8:

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

Argumento paraN&ATILDE;Ousando uma BOM:

A principal motivação para não usar uma BOM é a compatibilidade com software que não é compatível com Unicode ... Outra motivação para não usar uma BOM é encorajar a UTF-8 como a codificação "padrão".

ArgumentFORusando uma BOM:

O argumento para usar uma BOM é que, sem ela, a análise heurística é necessária para determinar qual codificação de caractere 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. Várias bibliotecas estão disponíveis para facilitar a tarefa, como o Mozilla Universal Charset Detector e o International Components for Unicode.

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

Em particular, Microsoftcompiladores e intérpretes, e muitos softwares no Microsoft Windows, como o Bloco de Notas, não lerão corretamente o texto UTF-8, a menos que tenha somente caracteres ASCIIou inicie com a BOM, e adicionará uma lista de materiais ao início ao salvar texto como UTF 8. O Google Docs adicionará uma lista de materiais quando um documento do Microsoft Word for baixado como um arquivo de texto simples.

Em que é melhor,COMouSEMa BOM:

O 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 uma assinatura."

Minha conclusão:

Use o BOM onlyse a compatibilidade com um aplicativo de software for absolutamente essencial.

Observe também que, embora o artigo da Wikipédia de referência indique que muitos aplicativos da Microsoft confiam na BOM para detectar corretamente o UTF-8, esse não é o caso de todos aplicativos da Microsoft. Por exemplo, como apontado por @barlop , ao usar o Prompt de Comando do Windows com UTF-8, os comandos type e more não esperam que o BOM esteja presente. Se o BOM is estiver presente, pode ser problemático como é para outras aplicações.


† O comando chcp oferece suporte para UTF-8 (sem a BOM) via página de código 65001 .

16
DavidRR

Deve-se notar que para alguns arquivos você não deve ter a lista de materiais mesmo no Windows. Exemplos são arquivos SQL*plus ou VBScript. Caso esses arquivos contenham um BOM, você receberá um erro quando tentar executá-los.

7
Wernfried Domscheit

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 é obrigatório nem recomendado para UTF-8, mas pode ser encontrado em contextos nos quais os dados UTF-8 são convertidos de outras formas de codificação que usam uma BOM ou onde a BOM é usada como uma assinatura UTF-8"

7
pib

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

Edit: Só quero deixar claro que eu prefiro não ter o BOM, adicione-o se algum lixo velho rompe com ele, e substituindo esse aplicativo legado não é viável.

Não faça nada esperar uma lista de materiais para UTF8.

7
James Wakefield

Quando você quiser exibir informações codificadas em UTF-8, você não poderá enfrentar problemas. Declarar, 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 no Linux.

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

Salve 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 que seja declarado como UTF-8.

Eu tinha uma série de dados contendo letras em francês, que precisavam ser salvos como XML para distribuição. Sem criar um arquivo UTF-8 desde o início (alterando opções em IDE e "Criar novo arquivo") ou adicionando a BOM no início do arquivo

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

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

6
Florin Sima

UTF-8 sem BOM não tem BOM, o que não o torna melhor do 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 BOM geralmente é útil para determinar o endianness da codificação, o que não é necessário para a maioria dos casos de uso.

Além disso, o BOM pode ser desnecessário ruído/dor para os consumidores que não sabem ou não se importam com isso, e podem resultar em confusão para o usuário.

6
Romain

Eu vejo isso de uma perspectiva diferente. Eu acho que UTF-8 com BOM é melhorcomo ele fornece mais informações sobre o arquivo. Eu uso UTF-8 sem BOM somente se eu enfrentar problemas.

Estou usando vários idiomas (até cirílico ) nas minhas páginas por um longo tempo e quando os arquivos são salvos sem BOM e reabrimo-los para edição com um editor (como cherouvim também anotado), alguns personagens estão corrompidos.

Note que o clássico do Windows Notepad salva automaticamente arquivos com um BOM quando você tenta salvar um arquivo recém-criado com a codificação UTF-8.

Eu pessoalmente salve server side arquivos de script (.asp, .ini, .aspx) com BOMe arquivos .html sem BOM.

6
user1358065

Uma diferença prática é que, se você escrever um script Shell para o Mac OS X e salvá-lo como simples UTF-8, você receberá 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 BOM (digamos em BBEdit ) ficará bem.

6
David

Essa pergunta já tem uma resposta de um milhão e uma, e muitas delas são muito boas, mas eu queria tentar esclarecer quando uma lista técnica deveria ou não ser usada.

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

Se um código de byte correspondente à lista de materiais UTF-8 for encontrado, a probabilidade é alta o suficiente para assumir que é UTF-8 e você pode ir a partir daí. Quando forçado a fazer essa suposição, no entanto, a verificação de erros adicional durante a leitura ainda seria uma boa ideia para o caso de algo parecer confuso. Você deve apenas assumir que uma BOM não é UTF-8 (ou seja, 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 a codificação.

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

  1. Software não compatível com Unicode ou mal-compatível pode assumir que é latin-1 ou ANSI e não tira a BOM da cadeia de caracteres, o que obviamente pode causar problemas.
  2. Ele não é realmente necessário (basta verificar se o conteúdo é compatível e sempre usar o UTF-8 como substituto quando nenhuma codificação compatível puder ser encontrada)

Quando deve você codifica com uma lista de materiais?

Se você não conseguir gravar os metadados de outra forma (por meio de uma tag charset ou meta do sistema de arquivos) e dos programas que estão sendo usados ​​como BOMs, você deverá codificar com uma BOM. Isso é especialmente verdadeiro no Windows, em que geralmente presume-se que qualquer coisa sem uma lista técnica esteja usando uma página de código legado. O BOM informa programas como o Office que, sim, o texto neste arquivo é Unicode; aqui está a codificação usada.

Quando se trata disso, os únicos arquivos com os quais realmente tenho problemas sã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ê desejar abri-la sem problemas e não precisar recorrer à importação dos dados.

6
jpc-ae

O Unicode Byte Ordem Mark (BOM) FAQ fornece uma resposta concisa:

P: Como devo lidar com as listas de materiais?

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ê precisa estar em conformidade com esse protocolo, use uma BOM.

  2. Alguns protocolos permitem BOMs opcionais no caso de texto não marcado. Nesses casos,

    • Quando um fluxo de dados de texto é conhecido como texto simples, 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 um fluxo de dados de texto é conhecido por ser um texto Unicode simples (mas não por qual endian), o BOM pode ser usado como uma assinatura. Se não houver BOM, o texto deve ser interpretado como big-endian.

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

  4. Onde o tipo preciso 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.

4
Wernfried Domscheit

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

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

Além disso, acabei de encontrar isso na Wikipedia:

Os caracteres Shebang são representados pelos mesmos dois bytes em codificações estendidas ASCII, incluindo UTF-8, que é comumente usado para scripts e outros arquivos de texto em sistemas atuais do tipo Unix. No entanto, os arquivos UTF-8 podem começar com a marca de ordem de byte 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 contra o uso da marca de ordem de byte em scripts POSIX (tipo Unix), [15] por essa razão e para interoperabilidade mais ampla e preocupações filosóficas.

4
Marek Möhling

De 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 de texto ou fluxo. Seu ponto de código é U + FEFF. O uso de BOM é 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 lista de materiais no seu arquivo garantirá que ela sempre abra corretamente em um editor que suporte UTF-8 e BOM.

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

abc

Sem o BOM, isso é aberto como ANSI na maioria dos editores. Então, outro usuário deste arquivo abre e acrescenta alguns caracteres nativos, por exemplo:

abg-αβγ

Ops ... Agora o arquivo ainda está em ANSI e adivinhe, "αβγ" não ocupa 6 bytes, mas 3. Isso não é UTF-8 e isso causa outros problemas mais tarde na cadeia de desenvolvimento.

1
cherouvim