¿Qué hay de diferente entre UTF-8 y UTF-8 sin BOM?

¿Qué hay de diferente entre UTF-8 y UTF-8 sin una lista de materiales ? ¿Cual es mejor?

La BOM UTF-8 es una secuencia de bytes (EF BB BF) que permite al lector identificar un archivo como codificado en UTF-8.

Normalmente, la lista de materiales se utiliza para señalar la endianidad de una encoding, pero como la endianidad es irrelevante para UTF-8, la lista de materiales no es necesaria.

De acuerdo con el estándar Unicode , no se recomienda la lista de materiales para archivos UTF-8 :

2.6 Esquemas de encoding

… El uso de una lista de materiales no es ni requerido ni recomendado para UTF-8, pero puede encontrarse en contextos donde los datos UTF-8 se convierten de otras formas de encoding que usan una lista de materiales o donde la lista de materiales se utiliza como una firma UTF-8 . Consulte la subsección “Marca de orden de bytes” en la Sección 16.8, Especiales , para obtener más información.

Las otras excelentes respuestas ya respondieron que:

  • No hay diferencia oficial entre UTF-8 y BOM-ed UTF-8
  • Una cadena BOM-ed UTF-8 comenzará con los tres siguientes bytes. EF BB BF
  • Esos bytes, si están presentes, se deben ignorar al extraer la cadena del archivo / secuencia.

Pero, como información adicional a esto, la lista de materiales para UTF-8 podría ser una buena manera de “oler” si una cadena estaba codificada en UTF-8 … O podría ser una cadena legítima en cualquier otra encoding …

Por ejemplo, los datos [EF BB BF 41 42 43] podrían ser:

  • La cadena legítima ISO-8859-1 “ï» ¿ABC ”
  • La cadena legítima UTF-8 “ABC”

Entonces, aunque puede ser genial reconocer la encoding de un contenido de archivo mirando los primeros bytes, no debe confiar en esto, como se muestra en el ejemplo anterior

Las codificaciones deben ser conocidas, no adivinadas.

Hay al menos tres problemas al colocar una lista de materiales en archivos codificados en UTF-8.

  1. Los archivos que no contienen texto ya no están vacíos porque siempre contienen la lista de materiales.
  2. Los archivos que contienen texto que está dentro del subconjunto ASCII de UTF-8 ya no son ellos mismos ASCII porque la lista de materiales no es ASCII, lo que hace que algunas herramientas existentes se descompongan, y puede ser imposible para los usuarios reemplazar dichas herramientas heredadas.
  3. No es posible concatenar varios archivos juntos porque cada archivo ahora tiene una lista de materiales al principio.

Y, como han mencionado otros, no es ni suficiente ni necesario tener una lista de materiales para detectar que algo es UTF-8:

  • No es suficiente porque puede suceder que una secuencia de bytes arbitraria comience con la secuencia exacta que constituye la lista de materiales.
  • No es necesario porque puede leer los bytes como si fueran UTF-8; si eso tiene éxito, es, por definición, UTF-8 válido.

Es una vieja pregunta con muchas buenas respuestas, pero se debe agregar una cosa.

Todas las respuestas son muy generales. Lo que me gustaría agregar son ejemplos del uso de BOM que en realidad causan problemas reales y, sin embargo, muchas personas no lo conocen.

BOM rompe scripts

Los scripts de Shell, los scripts de Perl, los scripts de Python, los scripts de Ruby, los scripts de Node.js o cualquier otro ejecutable que deba ser ejecutado por un intérprete, todo comienza con una línea de shebang que se ve como una de esas:

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

Le dice al sistema qué intérprete necesita ejecutarse al invocar dicho script. Si la secuencia de comandos está codificada en UTF-8, uno puede tener la tentación de incluir una lista de materiales al principio. Pero en realidad el “#!” los personajes no son solo personajes De hecho, son un número mágico que está compuesto por dos caracteres ASCII. Si coloca algo (como una lista de materiales) antes de esos personajes, entonces el archivo se verá como si tuviera un número mágico diferente y eso puede ocasionar problemas.

Ver Wikipedia, artículo: Shebang, sección: Número mágico :

Los caracteres shebang están representados por los mismos dos bytes en codificaciones ASCII extendidas, incluido UTF-8, que se usa comúnmente para scripts y otros archivos de texto en sistemas actuales tipo Unix. Sin embargo, los archivos UTF-8 pueden comenzar con la marca de orden de bytes opcional (BOM); si la función “exec” detecta específicamente los bytes 0x23 y 0x21, entonces la presencia de la BOM (0xEF 0xBB 0xBF) antes del shebang evitará que se ejecute el intérprete de guiones. Algunas autoridades recomiendan no utilizar la marca de orden de bytes en las secuencias de comandos POSIX (tipo Unix), [14] por esta razón y por una mayor interoperabilidad y preocupaciones filosóficas. Además, una marca de orden de bytes no es necesaria en UTF-8, ya que esa encoding no tiene problemas de endianness; sirve solo para identificar la encoding como UTF-8. [énfasis añadido]

BOM es ilegal en JSON

Ver RFC 7159, Sección 8.1 :

Las implementaciones NO DEBEN agregar una marca de orden de bytes al comienzo de un texto JSON.

BOM es redundante en JSON

No solo es ilegal en JSON, tampoco es necesario para determinar la encoding de caracteres porque hay formas más confiables de determinar inequívocamente tanto la encoding de caracteres como la endianidad utilizada en cualquier transmisión JSON (consulte esta respuesta para obtener más información).

BOM rompe los analizadores JSON

No solo es ilegal en JSON y no es necesario , realmente rompe todo el software que determina la encoding utilizando el método presentado en RFC 4627 :

Determinación de la encoding y endianness de JSON, examinando los primeros 4 bytes para el 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 

Ahora, si el archivo comienza con BOM se verá así:

 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 

Tenga en cuenta que:

  1. UTF-32BE no comienza con tres NUL por lo que no será reconocido
  2. UTF-32LE el primer byte no es seguido por 3 NULs por lo que no será reconocido
  3. UTF-16BE tiene solo 1 NUL en los primeros 4 bytes, por lo que no será reconocido
  4. UTF-16LE tiene solo 1 NUL en los primeros 4 bytes, por lo que no será reconocido

Dependiendo de la implementación, todos ellos pueden interpretarse incorrectamente como UTF-8 y luego malinterpretarse o rechazarse como UTF-8 no válido, o no ser reconocidos en absoluto.

Además, si la implementación prueba un JSON válido como recomiendo, rechazará incluso la entrada que efectivamente está codificada como UTF-8 porque no comienza con un carácter ASCII <128 como debería según el RFC.

Otros formatos de datos

La BOM en JSON no es necesaria, es ilegal y rompe el software que funciona correctamente de acuerdo con el RFC. Debería ser una herramienta sencilla para no utilizarlo en ese momento y, sin embargo, siempre hay personas que insisten en romper JSON mediante el uso de listas de materiales, comentarios, reglas de cotización diferentes o diferentes tipos de datos. Por supuesto, cualquiera puede usar cosas como listas de materiales o cualquier otra cosa si lo necesita, simplemente no lo llame JSON.

Para otros formatos de datos que JSON, observe cómo se ve realmente. Si las únicas codificaciones son UTF- * y el primer carácter debe ser un carácter ASCII menor que 128, entonces ya tiene toda la información necesaria para determinar tanto la encoding como la endianidad de sus datos. Agregar listas de materiales incluso como una función opcional solo lo haría más complicado y propenso a errores.

Otros usos de BOM

En cuanto a los usos fuera de JSON o scripts, creo que ya hay muy buenas respuestas aquí. Quería agregar más información detallada específicamente sobre scripting y serialización porque es un ejemplo de los caracteres de la BOM que causan problemas reales.

¿Qué hay de diferente entre UTF-8 y UTF-8 sin BOM?

Respuesta corta: en UTF-8, una BOM se codifica como los bytes EF BB BF al comienzo del archivo.

Respuesta larga:

Originalmente, se esperaba que Unicode estuviera codificado en UTF-16 / UCS-2. La lista de materiales fue diseñada para esta forma de encoding. Cuando tiene unidades de código de 2 bytes, es necesario indicar en qué orden están esos dos bytes, y una convención común para hacer esto es incluir el carácter U + FEFF como una “Marca de orden de byte” al comienzo de los datos. El carácter U + FFFE está permanentemente desasignado para que su presencia pueda usarse para detectar el orden de bytes incorrecto.

UTF-8 tiene el mismo orden de bytes independientemente del endianamiento de la plataforma, por lo que no es necesaria una marca de orden de bytes. Sin embargo, puede ocurrir (como la secuencia de bytes EF BB FF ) en los datos que se convirtieron en UTF-8 de UTF-16, o como una “firma” para indicar que los datos son UTF-8.

¿Cual es mejor?

Sin. Como Martin Cote respondió, el estándar Unicode no lo recomienda. Causa problemas con software no compatible con BOM.

Una mejor forma de detectar si un archivo es UTF-8 es realizar una verificación de validez. UTF-8 tiene reglas estrictas sobre qué secuencias de bytes son válidas, por lo que la probabilidad de un falso positivo es insignificante. Si una secuencia de bytes se parece a UTF-8, probablemente lo sea.

UTF-8 con BOM está mejor identificado. He llegado a esta conclusión por las malas. Estoy trabajando en un proyecto donde uno de los resultados es un archivo CSV , que incluye caracteres Unicode.

Si el archivo CSV se guarda sin una lista de materiales, Excel piensa que es ANSI y muestra un galimatías. Una vez que agrega “EF BB BF” al frente (por ejemplo, al volver a guardarlo usando el Bloc de notas con UTF-8 o Notepad ++ con UTF-8 con BOM), Excel lo abre bien.

El documento RFC 3629 recomienda agregar el carácter BOM a los archivos de texto Unicode: “UTF-8, un formato de transformación de ISO 10646”, noviembre de 2003 en http://tools.ietf.org/html/rfc3629 (esta última información se encuentra en: http://www.herongyang.com/Unicode/Notepad-Byte-Order-Mark-BOM-FEFF-EFBBBF.html )

BOM tiende a auge (sin juego de palabras (sic)) en algún lugar, en algún lugar. Y cuando está en auge (por ejemplo, no es reconocido por los navegadores, editores, etc.), aparece como los caracteres extraños  al comienzo del documento (por ejemplo, archivo HTML, respuesta JSON , RSS , etc.) y causa el tipo de situaciones embarazosas como el reciente problema de encoding experimentado durante la charla de Obama en Twitter .

Es muy molesto cuando aparece en lugares difíciles de depurar o cuando se descuidan las pruebas. Por lo tanto, es mejor evitarlo a menos que deba usarlo.

Pregunta: ¿Qué hay de diferente entre UTF-8 y UTF-8 sin una lista de materiales? ¿Cual es mejor?

Aquí hay algunos extractos del artículo de Wikipedia sobre la marca de orden de bytes (BOM) que creo que ofrecen una respuesta sólida a esta pregunta.

Sobre el significado de BOM y UTF-8:

El estándar Unicode permite la lista de materiales en UTF-8 , pero no requiere ni recomienda su uso. La orden de bytes no tiene ningún significado en UTF-8, por lo que su único uso en UTF-8 es señalizar al comienzo que la secuencia de texto está codificada en UTF-8.

Argumento para NO usar una lista de materiales:

La principal motivación para no usar una BOM es la compatibilidad con versiones anteriores de software que no es compatible con Unicode … Otra motivación para no usar una BOM es alentar a UTF-8 como la encoding “predeterminada”.

Argumento PARA usar una lista de materiales:

El argumento para usar una lista de materiales es que sin ella, se requiere un análisis heurístico para determinar qué carácter está usando la encoding de un archivo. Históricamente, dicho análisis, para distinguir varias codificaciones de 8 bits, es complicado, propenso a errores y, a veces, lento. Hay varias bibliotecas disponibles para facilitar la tarea, como Mozilla Universal Charset Detector y International Components for Unicode.

Los progtwigdores asumen erróneamente que la detección de UTF-8 es igualmente difícil (no es porque la gran mayoría de las secuencias de bytes no sean válidas UTF-8, mientras que las codificaciones que estas bibliotecas intentan distinguir permiten todas las secuencias de bytes posibles). Por lo tanto, no todos los progtwigs compatibles con Unicode realizan dicho análisis y, en cambio, dependen de la lista de materiales.

En particular, los comstackdores e intérpretes de Microsoft y muchas piezas de software en Microsoft Windows como el Bloc de notas no leerán correctamente el texto UTF-8 a menos que solo tenga caracteres ASCII o comience con la lista de materiales, y agregarán una lista de materiales al inicio al guardar texto como UTF-8. Google Docs agregará una lista de materiales cuando se descargue un documento de Microsoft Word como archivo de texto sin formato.

En el que es mejor, con o sin la lista de materiales:

El IETF recomienda que si un protocolo (a) siempre utiliza UTF-8, o (b) tiene alguna otra forma de indicar qué encoding se está utilizando, entonces “DEBERÍA prohibir el uso de U + FEFF como firma”.

Mi conclusión:

Use la lista de materiales solo si la compatibilidad con una aplicación de software es absolutamente esencial.

También tenga en cuenta que, si bien el artículo de Wikipedia mencionado indica que muchas aplicaciones de Microsoft se basan en la lista de materiales para detectar correctamente UTF-8, este no es el caso para todas las aplicaciones de Microsoft. Por ejemplo, tal como lo señala @barlop , al utilizar el símbolo del sistema de Windows con UTF-8 , los comandos de este type y more no esperan que la lista de materiales esté presente. Si la lista de materiales está presente, puede ser problemático como lo es para otras aplicaciones.


† El comando chcp ofrece soporte para UTF-8 ( sin la BOM) a través de la página de códigos 65001 .

Citado en la parte inferior de la página de Wikipedia en la lista de materiales: http://en.wikipedia.org/wiki/Byte-order_mark#cite_note-2

“El uso de una lista de materiales no es necesario ni recomendado para UTF-8, pero puede encontrarse en contextos donde los datos UTF-8 se convierten de otras formas de encoding que usan una lista de materiales o donde la lista de materiales se utiliza como firma UTF-8”

Miro esto desde una perspectiva diferente. Creo que UTF-8 con BOM es mejor, ya que proporciona más información sobre el archivo. Uso UTF-8 sin BOM solo si tengo problemas.

Estoy usando varios idiomas (incluso cirílico ) en mis páginas durante mucho tiempo y cuando los archivos se guardan sin BOM y los vuelvo a abrir para editarlos con un editor (como también se mencionó cherouvim ), algunos caracteres están dañados.

Tenga en cuenta que el Bloc de notas clásico de Windows guarda automáticamente los archivos con una BOM cuando intenta guardar un archivo recién creado con encoding UTF-8.

Personalmente guardo archivos de scripting del lado del servidor (.asp, .ini, .aspx) con archivos BOM y .html sin BOM .

UTF-8 sin BOM no tiene BOM, lo que no lo hace mejor que UTF-8 con BOM, excepto cuando el consumidor del archivo necesita saber (o se beneficiaría de saber) si el archivo está codificado en UTF-8 o no.

La lista de materiales suele ser útil para determinar la duración de la encoding, que no es necesaria para la mayoría de los casos de uso.

Además, la lista de materiales puede ser ruido / dolor innecesario para los consumidores que no la conocen o no les importa y puede provocar confusión entre los usuarios.

Cuando desee visualizar información codificada en UTF-8, es posible que no tenga problemas. Declare, por ejemplo, un documento HTML como UTF-8 y tendrá todo lo que se muestra en su navegador que figura en el cuerpo del documento.

Pero este no es el caso cuando tenemos archivos de texto, CSV y XML, ya sea en Windows o Linux.

Por ejemplo, un archivo de texto en Windows o Linux, una de las cosas más fáciles imaginables, no es (generalmente) UTF-8.

Guárdelo como XML y declare como UTF-8:

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

No se mostrará (no se leerá) correctamente, incluso si está declarado como UTF-8.

Tenía una cadena de datos con letras francesas que debían guardarse como XML para sindicación. Sin crear un archivo UTF-8 desde el principio (cambiando las opciones en IDE y “Crear nuevo archivo”) o agregando la lista de materiales al comienzo del archivo

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

No pude guardar las letras francesas en un archivo XML.

Debe tenerse en cuenta que para algunos archivos no debe tener la lista de materiales incluso en Windows. Los ejemplos son archivos SQL*plus o VBScript . En caso de que dichos archivos contengan una BOM, se obtiene un error cuando intenta ejecutarlos.

UTF-8 con BOM solo ayuda si el archivo contiene algunos caracteres que no son ASCII. Si está incluido y no hay ninguno, posiblemente rompa las aplicaciones anteriores que de otra manera hubieran interpretado el archivo como ASCII simple. Estas aplicaciones definitivamente fallarán cuando se encuentren con un carácter que no sea ASCII, por lo tanto, en mi opinión, la lista de materiales solo debe agregarse cuando el archivo ya no se pueda interpretar como ASCII simple.

Editar: Solo quiero aclarar que prefiero no tener la lista de materiales en absoluto, agregarla si algunos residuos viejos se rompen y no es posible reemplazar esa aplicación heredada.

No hagas esperar nada de una lista de materiales para UTF8.

Una diferencia práctica es que si escribe un script de shell para Mac OS X y lo guarda como UTF-8 simple, obtendrá la respuesta:

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

en respuesta a la línea de shebang que especifica qué shell desea utilizar:

 #!/bin/bash 

Si guarda como UTF-8, no BOM (por ejemplo en BBEdit ) todo estará bien.

Esta pregunta ya tiene respuestas de millones y una, y muchas de ellas son bastante buenas, pero quería intentar aclarar cuándo se debe utilizar una lista de materiales o no.

Como se mencionó, cualquier uso de la BOM de UTF (Marca de orden de bytes) para determinar si una cadena es UTF-8 o no es una conjetura educada. Si hay metadatos apropiados disponibles (como charset="utf-8" ), entonces ya sabes lo que se supone que debes usar, pero de lo contrario necesitarás probar y hacer algunas suposiciones. Esto implica verificar si el archivo del que proviene una cadena comienza con el código de bytes hexadecimal, EF BB BF.

Si se encuentra un código de bytes correspondiente a la BOM UTF-8, la probabilidad es lo suficientemente alta como para asumir que es UTF-8 y puede ir desde allí. Sin embargo, cuando se lo fuerce a adivinar, la comprobación de errores adicionales durante la lectura sería una buena idea en caso de que algo salga mal. Solo debe suponer que una BOM no es UTF-8 (es decir, latin-1 o ANSI) si la entrada definitivamente no debe ser UTF-8 en función de su origen. Sin embargo, si no hay una lista de materiales, simplemente puede determinar si se supone que es UTF-8 al validar la encoding.

¿Por qué no se recomienda una lista de materiales?

  1. El software no compatible con Unicode o poco compatible puede asumir que es latin-1 o ANSI y no eliminará la lista de materiales de la cadena, lo que obviamente puede causar problemas.
  2. En realidad no es necesario (solo verifique si el contenido es compatible y siempre use UTF-8 como alternativa cuando no se encuentre una encoding compatible)

¿Cuándo deberías codificar con una lista de materiales?

Si no puede grabar los metadatos de otra manera (mediante una etiqueta de conjunto de caracteres o metadatos del sistema de archivos) y los progtwigs que se utilizan como listas de materiales, debe codificar con una lista de materiales. Esto es especialmente cierto en Windows, donde generalmente se supone que todo lo que no tiene una lista de materiales utiliza una página de códigos heredada. El BOM le dice a progtwigs como Office que, sí, el texto en este archivo es Unicode; aquí está la encoding utilizada.

Cuando se trata de eso, los únicos archivos con los que realmente tengo problemas son CSV. Dependiendo del progtwig, debe o no debe tener una lista de materiales. For example, if you’re using Excel 2007+ on Windows, it must be encoded with a BOM if you want to open it smoothly and not have to resort to importing the data.

As mentioned above, UTF-8 with BOM may cause problems with non-BOM-aware (or compatible) software. I once edited HTML files encoded as UTF-8 + BOM with the Mozilla-based KompoZer , as a client required that WYSIWYG program.

Invariably the layout would get destroyed when saving. It took my some time to fiddle my way around this. These files then worked well in Firefox, but showed a CSS quirk in Internet Explorer destroying the layout, again. After fiddling with the linked CSS files for hours to no avail I discovered that Internet Explorer didn’t like the BOMfed HTML file. Nunca más.

Also, I just found this in Wikipedia:

The shebang characters are represented by the same two bytes in extended ASCII encodings, including UTF-8, which is commonly used for scripts and other text files on current Unix-like systems. However, UTF-8 files may begin with the optional byte order mark (BOM); if the “exec” function specifically detects the bytes 0x23 0x21, then the presence of the BOM (0xEF 0xBB 0xBF) before the shebang will prevent the script interpreter from being executed. Some authorities recommend against using the byte order mark in POSIX (Unix-like) scripts,[15] for this reason and for wider interoperability and philosophical concerns

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

The byte order mark (BOM) is a Unicode character used to signal the endianness (byte order) of a text file or stream. Its code point is U+FEFF. BOM use is optional, and, if used, should appear at the start of the text stream. Beyond its specific use as a byte-order indicator, the BOM character may also indicate which of the several Unicode representations the text is encoded in.

Always using a BOM in your file will ensure that it always opens correctly in an editor which supports UTF-8 and BOM.

My real problem with the absence of BOM is the following. Suppose we’ve got a file which contains:

 abc 

Without BOM this opens as ANSI in most editors. So another user of this file opens it and appends some native characters, for example:

 abg-αβγ 

Oops… Now the file is still in ANSI and guess what, “αβγ” does not occupy 6 bytes, but 3. This is not UTF-8 and this causes other problems later on in the development chain.

The Unicode Byte Order Mark (BOM) FAQ provides a concise answer:

Q: How I should deal with BOMs?

A: Here are some guidelines to follow:

  1. A particular protocol (eg Microsoft conventions for .txt files) may require use of the BOM on certain Unicode data streams, such as files. When you need to conform to such a protocol, use a BOM.

  2. Some protocols allow optional BOMs in the case of untagged text. In those cases,

    • Where a text data stream is known to be plain text, but of unknown encoding, BOM can be used as a signature. If there is no BOM, the encoding could be anything.

    • Where a text data stream is known to be plain Unicode text (but not which endian), then BOM can be used as a signature. If there is no BOM, the text should be interpreted as big-endian.

  3. Some byte oriented protocols expect ASCII characters at the beginning of a file. If UTF-8 is used with these protocols, use of the BOM as encoding form signature should be avoided.

  4. Where the precise type of the data stream is known (eg Unicode big-endian or Unicode little-endian), the BOM should not be used. In particular, whenever a data stream is declared to be UTF-16BE, UTF-16LE, UTF-32BE or UTF-32LE a BOM must not be used.

UTF with BOM is better if you use UTF-8 in HTML files, if you use Serbian Cyrillic, Serbian Latin, German, Hungarian or something exotic language in the same page. That is my opinion (30 years of computing and IT industry).