En Unicode, l'indicateur d'ordre des octets ou BOM (pour l'anglais byte order mark) est une donnée qui indique l'utilisation d'un encodage unicode ainsi que l'ordre des octets, généralement situé au début de certains fichiers texte.
Techniquement, il s'agit d'un caractère Unicode de point de code U+FEFF (espace insécable sans chasse ou en anglais zero-width no-break space), quand ce caractère est utilisé pour marquer l'endianness (boutisme) d'une chaîne de caractères UCS/Unicode codée en UTF-16 ou UTF-32 et/ou comme marqueur pour indiquer que le texte est codé en UTF-8, UTF-16 ou UTF-32. Le terme officiel dans la version française de l'ISO/CEI 10646, qui est le pendant ISO d'Unicode, de ce caractère est indicateur d'ordre des octets (IOO).
Lorsqu'il est correctement interprété, l'IOO n'est pas vu par l'utilisateur final du texte codé. Il existe cependant deux cas où ce caractère peut être mal interprété :
L'indicateur d'ordre des octets de la plupart des codages Unicode est une séquence de quelques octets qui peut apparaître comme une obscure séquence de caractères si le logiciel utilisé pour lire le texte est mal configuré ou comme une espace si le logiciel utilisé pour lire le texte ne sait pas reconnaître cet indicateur.
Si un indicateur d'ordre des octets est interprété à tort comme un caractère à l'intérieur du texte, alors il sera invisible en raison du fait que c'est une espace insécable sans chasse (c'est-à-dire de largeur nulle). L'utilisation du caractère U+FEFF comme une espace insécable sans chasse, autrement dit en tant que gluon de mot, a été rendue obsolète dans la version Unicode 3.2, qui fournit une alternative U+2060 pour cette utilisation. Ce caractère doit donc être utilisé seulement en tant qu'indicateur d'ordre des octets.
En 2001, le bug 4508058 est identifié dans Java « UTF-8 encoding does not recognize initial BOM ». Il est décidé de ne pas le corriger. Il a été corrigé vers 2006/2007[5],[6].
En , la problématique du BOM est considérée par le RFC 3629[7].
Entre et 2009, la problématique de l'indicateur d'ordre des octets a été prise en compte dans le langage Python à travers le document PEP 263 « Defining Python Source Code Encodings »[8] (PEP signifiant Python enhancement proposal, c'est-à-dire proposition d'amélioration de Python).
Avant le , Microsoft a introduit une fonctionnalité de compatibilité Unicode dans le logiciel notepad qui casse l'interopérabilité avec certains anciens logiciels Unix qui ne s'y étaient pas préparés[9].
En , un outil nommé bomstrip est développé pour donner un moyen aux utilisateurs, au cas par cas, de pallier les incompatibilités entre les nouveaux logiciels introduisant l'utilisation de l'indicateur BOM et les anciens ne s'y attendant pas[10].
En , un patch pour le noyau Linux est proposé pour permettre l'utilisation du BOM conjointement avec le shebang[11].
En , Visual Studio 2005 prend en charge les sources Unicode avec BOM dans le compilateur et l'éditeur de liens[12].
En , un bug est découvert dans la manière dont le serveur Web Apache gère les fichiers de configuration[13].
Le a lieu la sortie de la version Etch, c'est-à-dire la 4.0, de Debian qui est pré-configurée pour l'utilisation d'UTF-8. les codages précédents sont alors annoncés comme étant obsolètes[14].
En , un bug lié à la non acceptation de l'indicateur d'ordre des octets est détecté et corrigé aussitôt dans le compilateur GCC Fortran[15].
En , un bug lié à la non acceptation du l'indicateur d'ordre des octets est détecté et corrigé en avril 2008 dans le compilateur GCC[16].
En , un bug similaire a été détecté dans l'import des fichiers CSV par OpenOffice, il a été corrigé en , sous le nom dev300_m101[17].
Dans la version d'Unicode 6.1, de , ces informations restent valables et sont documentées dans la section « 16.8 Specials ».
En UTF-16, l'indicateur d'ordre des octets est représenté par une séquence de deux octets FE FF au début de la chaîne codée, pour indiquer que les caractères codés suivants utilisent l'ordre gros-boutien ; ou, si la séquence est FF FE pour indiquer l'ordre petit-boutien[18]. Parce que le standard Unicode garantit que le point de code U+FFFE n'est associé à aucun caractère Unicode, et par contraste avec U+FEFF qui est un caractère, cette séquence de deux octets suffit à déterminer l'ordre des octets.
Selon le même principe, l'indicateur d'ordre des octets peut être utilisé en UTF-32.
Alors que le codage de caractères UTF-8 ne pose pas de problème d'ordre des octets[19], l'indicateur d'ordre des octets est parfois utilisé pour déterminer qu'un texte est bien encodé en UTF-8. En effet, dans un souci d'interopérabilité, certains systèmes gèrent en plus d'UTF-8, un codage de caractères plus ancien, comme ISO/CEI 8859-1. Dans ce cas, l'indicateur peut être utilisé en tête d'un texte UTF-8 pour le distinguer d'un texte utilisant le codage de caractères ancien[20].
Cette technique repose sur l'hypothèse que la séquence d'octets correspondant à l'indicateur d'ordre des octets en UTF-8 a une très faible probabilité de présence dans un texte encodé dans le codage de caractères ancien. C'est notamment le cas en ISO 8859-1. En effet, en UTF-8, l'indicateur d'ordre des octets est codé par la séquence EF BB BF, qui correspond en ISO 8859-1 au texte «  ».
Bien que cette méthode permette une distinction rapide et précise de l'UTF-8, elle n'est pas reconnue par tous les logiciels et pose donc des problèmes de compatibilité. Le consortium Unicode définit bien cet usage de l'indicateur d'ordre des octets, mais n'a pas adopté une position tranchée qui viserait à en interdire ou à en recommander l'usage[21]. Cette indécision a sans doute attisé les problèmes d'interopérabilité entre les logiciels qui font une utilisation massive de l'indicateur, notamment sous Windows, et les logiciels dont les développeurs considèrent que son utilisation est suffisamment marginale pour s'en préoccuper, notamment sous certains Unix.
Par exemple, le caractère Unicode de point de code U+233B4 (caractère chinois signifiant « souche d'un arbre ») lorsqu'il suit l'indicateur d'ordre des octets est codé avec la séquence d'octets suivant[7] :
EF BB BF | F0 A3 8E B4 | ... |
Certains logiciels fonctionnant sous Unix, de conception ancienne, ont été développés pour fonctionner avec de l'ASCII étendu. La notion d'ASCII étendu fixe le fonctionnement du logiciel sur la plage ASCII tout en étant relativement compatible et transparent sur les octets non-ASCII. De ce fait, sans qu'ils aient été conçus pour traiter des fichiers UTF-8, ces logiciels sont relativement compatibles avec UTF-8, bien que l'indicateur d'ordre des octets soit une pierre d'achoppement. En effet, d'un point de vue conceptuel, accepter un indicateur d'ordre des octets UTF-8 reviendrait à accorder plus d'importance au standard UTF-8 qu'aux autres codages de caractères, ce qui est contraire à la logique orientée octet et multi-encodage qui prévalait jusqu'alors. Certains logiciels des distributions Linux ont quand même été adaptés.
Depuis 2005, cette approche se trouve confrontée à la réalité que beaucoup de logiciels Windows (incluant Windows Notepad) et l'environnement Visual Studio/.NET ajoutent un indicateur d'ordre des octets aux fichiers UTF-8.
Sur des logiciels des systèmes de type Unix (qui utilisent beaucoup les fichiers textes pour la configuration) cette pratique n'est pas recommandée.
On peut même la déconseiller, lorsqu'il s’avère nécessaire de supprimer manuellement l'indicateur d'ordre des octets UTF-8 pour les logiciels incompatibles qui ne peuvent pas les supprimer d'eux-mêmes. C'est en particulier le cas pour les scripts ayant recours au shebang au début d'un script interprété[22]. Il peut également interférer avec l'analyse lexicale des langages de programmation lorsque leur compilateur ne le reconnait pas. Par exemple, GCC indique des stray characters au début du fichier source[23], et en PHP 5, si la mise en cache de la sortie (en anglais, output buffering) est désactivée, cela a pour effet subtil de faire que la page commence immédiatement à être envoyée au navigateur, et d'empêcher la modification des en-têtes HTTP par le script PHP.
Dans les éditeurs de texte et navigateurs mal préparés pour traiter l'UTF-8, en codage ISO-8859-1, l'indicateur apparaît comme "".
Ils peuvent également échouer à appliquer la première règle d'une feuille CSS[24] ou faire échouer l'utilisation de certaines fonctions PHP5 (simplexml_load_file() par exemple).
Lorsque l'indicateur d'ordre des octets n'est pas utilisé, un éditeur de texte peut ne pas reconnaître le format UTF-8, modifier le texte sans respecter le format UTF-8, et ensuite rendre inopérante l’auto-détection de l'UTF-8.
Les alternatives au BOM peuvent être une auto-détection de l'UTF-8, qui statistiquement devrait marcher dans la plupart des cas sur un fichier, avec de rares erreurs. Toutefois cette technique ne peut pas marcher de manière fiable sur un flux quelconque car elle nécessiterait d'avoir reçu le flux en entier avant de commencer le traitement. Cette alternative échoue également sur un fichier contenant un agrégat de textes dont certains sont altérés ou ne sont pas en UTF-8.
La FAQ du standard Unicode[25] donne quatre réponses à la question de l'usage du BOM :
Apple a publié un ensemble de directives pour les programmeurs sur le comportement d'une application face à un fichier texte Unicode[26]. Ces directives leur prescrivent :
Codage | Séquence d'octets (Représentation) |
---|---|
UTF-8 | EF BB BF |
UTF-16 Big Endian | FE FF |
UTF-16 Little Endian | FF FE |
UTF-32 Big Endian | 00 00 FE FF |
UTF-32 Little Endian | FF FE 00 00 |
SCSU | 0E FE FF |
UTF-7 | 2B 2F 76 et l'un des octets suivants : [ 38 | 39 | 2B | 2F ] |
UTF-EBCDIC | DD 73 66 73 |
BOCU-1 | FB EE 28 |
UTF-1 | F7 64 4C |
Le standard Unicode n'impose pas l'indicateur d'ordre des octets en début de flux de données Unicode, mais le permet; c'est le cas en particulier pour UTF-8, où l'indicateur est facultatif.
Son acceptabilité dépend des protocoles utilisés. À des fins d'interopérabilité, les logiciels ont tendance à le reconnaître lorsqu'il est présent, et les utilisateurs à l'enlever lorsqu'il n'est pas reconnu par un logiciel.
P. Andries, Unicode 5.0 en pratique, Paris, Dunod, 2008.