O que há de diferente entre UTF-8 e UTF-8 sem uma lista técnica ? Qual é melhor?
O que há de diferente entre UTF-8 e UTF-8 sem uma lista técnica ? Qual é melhor?
Respostas:
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.
As outras excelentes respostas já responderam que:
EF BB BF
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:
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.
Há pelo menos três problemas ao colocar uma BOM em arquivos codificados em UTF-8.
E, como outros já mencionaram, não é suficiente nem necessário ter uma lista técnica para detectar que algo é UTF-8:
cat
não lhe dará um resultado limpo , um resultado que só tem BOM no começo. Se você quis dizer isso, é porque cat
funciona no nível de bytes, não no nível de conteúdo interpretado e, de maneira semelhante, cat
nã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.
Aqui estão exemplos do uso da lista técnica que realmente causam problemas reais e, no entanto, muitas pessoas não sabem disso.
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]
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.
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).
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:
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.
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.
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.
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 BF
no 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 é.
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.
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 )
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.
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 type
e more
nã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 chcp
comando oferece suporte para UTF-8 ( sem a BOM) através da página de códigos 65001 .
.htaccess
e gzip compression
em 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
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.
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.
Note-se que, para alguns arquivos, você não deve ter a lista técnica nem no Windows. Exemplos são SQL*plus
ou VBScript
arquivos. Caso esses arquivos contenham uma lista técnica, você receberá um erro ao tentar executá-los.
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.
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"
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.
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 .
chcp 65001
para suporte ao utf8, é utf8 sem bom. Se você fizer type myfile
isso, apenas será exibido corretamente se não houver bom. Se você fizer echo aaa>a.a
ou echo אאא>a.a
enviar os caracteres para o arquivo aa e tiver o chcp 65001, ele será exibido sem BOM.
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.
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.
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.
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:
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.
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.
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.
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.
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.
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).
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:
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).