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é 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é :
- 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 , 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)[1].
- En , 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)[2].
- En , 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[3].
- Jusqu'à Unicode 3.2, en , 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[4].
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 ».
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[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.
UTF-8
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 | ... |
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é[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).
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[25] 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[26]. 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) |
---|---|
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.
Références
- Liste des noms d'entités en Unicode 1.1, Révision du 5 juillet 1995 (1.1.5)
- The Unicode standard version 2.0, chapitre 2
- The Unicode Standard 3.0, chapitre 13
- Unicode 3.2: 3.9 Special Character Properties (revision)
- Bug 6378911 de la base Oracle: «UTF-8 decoder handling of byte-order mark has changed»
- (en) "JDK-4508058 : UTF-8 encoding does not recognize initial BOM"
- (en) F. Yergeau, « RFC 3629: UTF-8, a transformation format of ISO 10646 », IETF,
- (en) Marc-André Lemburg et Martin von Löwis, « PEP 263: Defining Python Source Code Encodings », Python (consulté le )
- (en) Michael S. Kaplan, program manager chez Microsoft, « Every character has a story #4: U+feff (alternate title: UTF-8 is the BOM, dude!) », MSDN, (consulté le )
- « Bomstrip - strip byte-order-marks from utf-8 files », sur ueber.net (consulté le ).
- (en) "Martin_v._Löwis" <martin () v ! loewis ! de>, « [Patch] Support UTF-8 scripts », linux-kernel, 2005-08-13 12:07:34
- Prise en charge Unicode dans le compilateur et l'éditeur de liens, MSDN (lire en ligne)
- (en) Bug 41529 - Accept BOM in .htaccess
- (en) Notes de publication pour Debian GNU/Linux 4.0 (« etch »), PA-RISC, Debian (lire en ligne)
- Bug gcc 31645 - Error on reading Byte Order Mark
- Bug gcc 33415: Can't compile .cpp file with UTF-8 BOM.
- Bug 89314 - CSV import should recognize Unicode BOM
- (en) « Utf-8, utf-16, utf-32 & bom », sur unicode.org (consulté le ).
- (en) « FAQ - UTF-8, UTF-16, UTF-32 & BOM: Can a UTF-8 data stream contain the BOM character (in UTF-8 form)? If yes, then can I still assume the remaining UTF-8 bytes are in big-endian order? » (consulté le ) : « [A BOM] makes no difference as to the endianness of the byte stream. UTF-8 always has the same byte order. »
- (en) « Utf-8, utf-16, utf-32 & bom », sur unicode.org (consulté le ).
- (en) « Unicode 5.0.0, Chapter 2 General Structure » (consulté le ) : « Use of a BOM is neither required nor recommended for UTF-8, but may be encountered in contexts where UTF-8 data is converted from other encoding forms that use a BOM or where the BOM is used as a UTF-8 signature », p. 36
- (en) Markus Kuhn, « UTF-8 and Unicode FAQ for Unix/Linux: What different encodings are there? », (consulté le ) : « Adding a UTF-8 signature at the start of a file would interfere with many established conventions such as the kernel looking for “#!” at the beginning of a plaintext executable to locate the appropriate interpreter. »
- (en) « GCC Mailing List: Re: How to compile c++ code without strip off utf-8 BOM? » : « error: stray '\357' in program »
- (en) FAQ: Display problems caused by the UTF-8 BOM, W3C i18n
- « UTF-8, UTF-16, UTF-32 & BOM », Unicode
- (en) Apple, « Universal Binary Programming Guidelines, Second Edition » (consulté le )
Voir aussi
Articles connexes
Liens externes
- Unicode en français, chapitre 14
- The Unicode Standard, chapter 13 (PDF) (see 13.6 — Specials)
- FAQ — UTF and BOM
Bibliographie
P. Andries, Unicode 5.0 en pratique, Paris, Dunod, 2008.