# Indicateur d'ordre des octets

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ée 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 de ce caractère dans la version française de l'ISO/CEI 10646, qui est le pendant ISO d'Unicode, 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é :
* Dans le cas où une version Unicode plus ancienne est considérée, ce caractère est un caractère invisible qui n'est pas affiché à l'utilisateur.
* Dans le cas d'un texte Unicode UTF-8 affiché avec un mauvais encodage (c'est-à-dire que l'encodage utilisé n'est pas celui qui devrait être utilisé), l'utilisateur est confronté en début de page/texte à une courte séquence incompréhensible de caractères sans signification : en particulier avec l'encodage ISO/CEI 8859-1, les trois caractères ï»¿ apparaissent au début de texte. Du fait que l'encodage utilisé n'est pas le bon, certains caractères régionaux ou accentués ne sont alors pas non plus affichés correctement dans la suite du texte.
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.

## Histoire

* En juillet 1995, la version Unicode 1.1.5 définit « FEFF;ZERO WIDTH NO-BREAK SPACE;Zs;0;ON;;;;;N;BYTE ORDER MARK;;;; » et ne définit pas ni le point de code FEFE ni le FEFD. La liste s'arrête à la valeur précédente : U+FEFC (ARABIC LIGATURE LAM WITH ALEF FINAL FORM).
* En juillet 1996, la version Unicode 2.0 définit dans ces sections §2.3 et §2.4 le rôle de la séquence FFFE/FEFF pour détecter l'ordre des octets (petit/gros-boutien).
* En septembre 1999, la version 3.0 de Unicode reprend ce qui est défini dans la version 2.0. Toutefois, est rajouté dans la section §13.6 une explication des utilisations de l'indicateur d'ordre des octets en UTF-16 comme en UTF-8.
* Jusqu'à Unicode 3.2, en mars 2002, U+FEFF était le seul point de code ayant une sémantique de gluon de mot (en anglais, word joining), mais comme il est plus communément utilisé comme indicateur d'ordre des octets, la sémantique de gluon de mot est donnée au point de code U+2060. Toutefois U+FEFF conserve les deux significations par compatibilité ascendante.
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$^,$.
En novembre 2003, la problématique du BOM est considérée par le RFC 3629.
Entre juin 2001 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 » (PEP signifiant Python enhancement proposal, c'est-à-dire proposition d'amélioration de Python).
Avant le 25 janvier 2005, 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.
En juillet 2005, 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.
En août 2005, un patch pour le noyau Linux est proposé pour permettre l'utilisation du BOM conjointement avec le shebang.
En octobre 2005, Visual Studio 2005 prend en charge les sources Unicode avec BOM dans le compilateur et l'éditeur de liens.
En février 2007, un bug est découvert dans la manière dont le serveur Web Apache gère les fichiers de configuration.
Le 8 avril 2007 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.
En avril 2007, 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.
En septembre 2007, 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.
En mai 2008, un bug similaire a été détecté dans l'import des fichiers CSV par OpenOffice, il a été corrigé en avril 2011, sous le nom dev300_m101.
Dans la version d'Unicode 6.1, de janvier 2012, ces informations restent valables et sont documentées dans la section « 16.8 Specials ».

## Usages
### UTF-16 et UTF-32

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

### UTF-8

Alors que le codage de caractères UTF-8 ne pose pas de problème d'ordre des octets, 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.
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. 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 :
| EF BB BF | F0 A3 8E B4 | ... |

#### Problèmes liés à l'utilisation de l'indicateur d'ordre des octets

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é. 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, 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 ou faire échouer l'utilisation de certaines fonctions PHP5 (simplexml_load_file par exemple).

#### Problèmes liés à la non-utilisation de l'indicateur d'ordre des octets

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.

### Alternatives

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.

### Guide du consortium Unicode

La FAQ du standard Unicode donne quatre réponses à la question de l'usage du BOM :
* un protocole particulier (comme les conventions des fichiers .txt de Microsoft) peuvent utiliser le BOM sur certains flux de données Unicode comme les fichiers. Il faut utiliser le BOM si l'on souhaite se conformer à ce protocole ;
* certains protocoles permettent l'utilisation optionnelle du BOM pour des textes non marqués. Dans ce cas, le BOM peut aider à la reconnaissance de l'encodage ;
* certains protocoles orientés octets nécessitent des caractères ASCII au début du fichier. Lorsqu'UTF-8 est utilisé dans ces protocoles l'utilisation du BOM servant à définir l'encodage devrait être évité ;
* lorsque le type de donnée (et d'encodage) est connu précisément le BOM ne devrait pas être utilisé.

### Directives Apple

Apple a publié un ensemble de directives pour les programmeurs sur le comportement d'une application face à un fichier texte Unicode. Ces directives leur prescrivent :
* d'accepter le BOM lors de la récupération de fichiers UTF-8 ou UTF-16 venant de l'extérieur ;
* d'utiliser les types natifs de manière interne;
* de générer un BOM lors de l'écriture d'un fichier UTF-16.

## Représentations des indicateurs d'ordre d'octets par codage

| Codage | Séquence d'octets (Représentation hexadécimale) |
| 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.