La question peut sembler simpliste à première vue, mais… Elle l’est !
En fait, c’est un problème que l’on peut facilement rencontrer sans vraiment s’en apercevoir et sur lequel il est possible de rester des heures sans trouver de réponse.
Qu’est-ce que UTF-8 avec BOM ou sans ?
UTF-8, pour « UCS transformation format 8 bits », est un format de codage de caractères. L’avantage principal de ce format est qu’il permet de coder des milliers de caractères et donc d’être utilisable dans de nombreuses langues.
L’inconvénient principal est que tous les logiciels ne l’utilisent pas.
Mais comme tous les navigateurs comprennent l’UTF-8, il est de bon goût d’utiliser cet encodage pour vos pages HTML.
Le codage UTF-8 « standard », donc avec BOM (pour « Byte Order Mark ») rajoute un caractère en début de fichier. Un espace insécable de largeur nulle « zero-width no-break space ». Ce caractère est invisible pour l’utilisateur. En fait, ce caractère n’a pas d’intérêt en UTF-8. Il est utile en UTF-16 ou UTF-32.
Le codage sans BOM ne place pas ce caractère, tout simplement.
Quel est le problème alors ?
Étant donné qu’un caractère est ajouté en début de fichier, vous comprendrez peut-être que cela va poser problème pour certain fichiers PHP. En effet, si vous désirez faire une redirection dans le fichier PHP avec « header()« , vous risquez d’avoir une erreur car un contenu aura déjà été envoyé au navigateur avant même que votre redirection commence.
Prenons par exemple le code suivant :
<?php
//————- Test d’encodage
header(« Location: ma-page.php »);
?>
Si vous codez votre fichier en UTF-8, vous aurez une erreur. Si vous le codez en UTF-8 sans BOM, vous n’aurez pas d’erreur.
L’erreur que vous risquez d’obtenir est la suivante :
Warning: Cannot modify header information – headers already sent by (output started at C:\www\monsite\test.php:1) in C:\www\monsite\test.php on line 3
Vous risquez également d’obtenir des décalages dans votre page si vous incluez un fichier codé en UTF-8.
Les solutions
En fait, la première solution consiste tout simplement à coder vos fichiers en UTF-8 sans BOM si votre éditeur de texte préféré le permet. Sinon, changez d’éditeur…
L’autre solution, si vous avez accès au php.ini de votre serveur, est de configurer « output_buffering » avec une valeur de 4096 (par exemple). Cela permet de mettre en buffer les pages avant de les envoyer au navigateur. Ce qui permet de corriger le problème de la redirection, mais pas des décalages dans vos pages. En même temps, vous accélérerez un peu la vitesse de création de pages.
Dernière solution, utilisez un autre codage que l’UTF-8. Pas forcément une bonne solution, mais si vous n’avez pas le choix…
Vous voilà prévenu maintenant. Si vous rencontrez un problème de redirection qui ne marche pas ou des décalages dans vos pages (avec des fichier inclus), et que vous n’arrivez vraiment pas à savoir pourquoi, vérifiez le codage de vos fichiers !
informations précises, complètes, sans « flafla… » et totalement utiles.
Je garde votre site bien au chaud
Merci!
Merciiiiiiiiiiiiiiiiiiiiiiiiii pour ces infos.
J’ai galéré pendant un certain temps avec ce « warning » et une fois le « warning » corrigé j’avais ce problème de caractères;
Vive les gens qui donnent des solutions simples et claires
Encore MERCI
Un seul regret :
Que cette page ne soit pas la PREMIERE référencée dans Google quand on cherche sur cette fichue erreur « Warning: Cannot modify header information – headers already sent »
Que de temps perdu alors que tout est là…
Même le DVD de formation d’Elephorm (PHP/MySQL) conseille UTF-8 au lieu de UTF-8 (sans BOM)… du coup on se coltine dans plantages pour « rien », à part se former un peu plus par le biais des forums 😐
La solution ne fonctionne pas chez moi.
Le soucis auquel je suis confronté à l’heure actuelle rassemble tous les stigmates du BOM / no BOM. Suis en dev de site sous joomla 2.5 sur lequel j’ai un formulaire à partir duquel il faut que je génère un document pdf de fpdf. Donc les 2 entités (formulaire et fpdf) marchent bien indépendemment mais des lors que je mets mon output() pour fpdf dans traitement php du formulaire, j’obtiens un « FPDF error: Some data has already been output, can’t send PDF file »…
J’ai essayé de modifier le php.ini de mon serveur (MAMP) mais cela ne change rien. Je travaille sous mac : pas de notepad++.
C’est très spécifique comme cas.
Quoi qu’il en soit, on en revient, à priori, toujours au même problème : il y a au moins un caractères, visible ou non, qui est envoyé avant le début du Php.
Soit c’est le Php qui a déjà envoyé un truc, soit le coup du BOM.
Une erreur qui arrive souvent en Php : il faut éviter de fermer les balises Php à la fin des fichiers inclus. Cela évite de se retrouver avec un retour à la ligne juste après la balise de fermeture (et question sécurité, c’est mieux).
un grand MERCI !
votre article vient de mettre un terme à plusieurs heures de recherche sur un problème d’affichage incorrect d’une page web!
Que de temps perdu pour un petit caractère invisible…
Bonjour, et merci.
Je viens, moi aussi de comprendre ce qui se passait chez moi. J’ai donc « transformer » mes pages en utf-8 sans BOM. Reste un souci, toutes les lettres accentuées se sont « transformées » aussi à l’affichage.
Y a-t-il une solution simple que de repasser sur toutes les lettres accentuées ? Merci.
L’encodage a très certainement été perdu, il va être difficile de le récupérer.
À moins que ce ne soit qu’un problème d’affichage dans le navigateur, auquel cas, il faut juste indiquer que l’encodage de la page est en UTF-8 et non en ISO-8859 ou autre.
Mais oui bien sûr !!! c’est ça que j’ai oublié de faire. Modifier l’encodage des pages.
Merci. Merci. Merci.
Que des compliments pour les explications. Précis simple et appliqué.
Par contre le gris des caractères et un peu trop clair à mon goût.
Je viens de modifier ce gris un peu trop clair 😉
Merci, j’avais une marge verticale trop importante avant un titre parce que le navigateur passait en mode Quirks (ce qui arrive quand on a quoi que ce soit avant le <!DOCTYPE …). Merci encore 🙂
Après avoir trouvé moi-même la solution du problème au bout d’une demi-heure de recherche (je venais d’encoder en UTF un fichier avec un header(« Location:index.php »);, j’en trouve l’explication précise dans ce site alors que beaucoup d’autres tournent autour du pot. Merci pour vos lumières.
Merci. Je vois qu’après 5 ans votre enseignement reste toujours utile. En islam ça s’appelle faire une Oeuvre utile et profitable.
« Le codage UTF-8 « standard », donc avec BOM (pour « Byte Order Mark ») rajoute un caractère en début de fichier. Un espace insécable de largeur nulle « zero-width no-break space ». Ce caractère est invisible pour l’utilisateur. En fait, ce caractère n’a pas d’intérêt en UTF-8. Il est utile en UTF-16 ou UTF-32. »
C’est relativement faux et surtout incomplet.
BOM signifie bien Byte Order Mark et oui, il permet, dans le cas de l’UTF-16 et de l’UTF-32 (entre autres) de connaître l’ordre des octets (endianness/boutisme) selon que l’architecture qui a produit le fichier préfère mettre les poids forts en premier ou en dernier.
Mais pas que.
Dans le cas de l’UTF-8, qui n’encode pas TOUS les caractères sur 2 ou 4 octets et n’a donc pas besoin de renseigner sur le boutisme utilisé, on pourrait penser qu’il est inutile.
Mais ce serait oublier que l’encodage des caractères accentués (entre autres) peut se faire de diverses manières à l’aide d’alphabets « Ansi », « Windows », etc. et que si le fichier est considéré en tant que tel, sans balise ou autre tag extérieur, il n’y a aucun moyen de savoir à priori comment en traiter le contenu.
En l’absence de BOM, on peut penser que le fichier, dans un environnement Windows a un encodage « Windows-1252 ».
Si l’on suspecte un possible encodage UTF8, il faut alors partir à la chasse aux séquences peu probables dans le fichier. En effet, si on rencontre un A majuscule orné d’un tilde suivi d’un signe copyright alors on peut penser qu’il ne s’agit pas d’un texte utilisant l’encodage dur un octet « Windows-1252 » mais d’un texte encodé en UTF-8 et la séquence de ces deux octets é est en fait représentatif d’un e accent aigu minuscule é.
Ouffffffffff.
Et s’il n’y a pas cette séquence, il y en peut être une autre, etc. bon on a de la chance, en français, on utilise rarement les caractères  et Ã, il suffit en fait de trouver une séquence dans l’espace C2+A0 à C2+BF ou C3+80 à C3+BF pour se dire qu’on a de très grandes chances ‘être en présence d’un texte en UTF-8.
Et si on avait la bonne idée de placer les octets EF+BB+BF au tout début ? ça ne veut rien dire dans aucune langue et on saurait tout de suite qu’on a à faire à un fichier en UTF-8. La procédure de lecture du fichier sait alors qu’il faut commencer la lecture du contenu utile à partir du 4ème octet.
Ça sert aussi à ça un BOM dans les fichiers UTF8 !
En ce qui concerne l’ « espace insécable de largeur nulle « zero-width no-break space ». » il avait effectivement un code Unicode qui correspondait aux différents BOM pour les 4 encodages UTF-16 et UTF-32 mais c’est du passé et ce n’est surtout pas le cas de l’UTF-8.
J’espère avoir éclairci ce débat. 🙂
Merci.
Bonsoir,
Je crois bien mettre enfin la main sur LA réponse seulement j’ai une question surement idiote puique personne n’a eu besoin d’y répondre :
Faut-il changer qui se situe entre les balises ?
Car je ne comprends pas bien comment convertir ce utf-8 classique en utf-8 sans BOM. Je travaille avec l’éditeur de texte gedit.
Merci de m’éclairer, car pour moi la galère touche presque à sa fin…
J’utilise Notepad++ pour faire la conversion. Il est gratuit et fonctionne sur toutes les plateformes : https://notepad-plus-plus.org/fr/
Bonjour Prélude,
J’étais sur gedit et là je viens de me réinstaller sublime text qui semble être par défaut en utf-8 sans BOM d’après ce que j’ai lu.
Je comprends que la question que je posais précédemment ne soit pas claire car un bout de mon texte a sauté.
Je disais donc : Faut-il changer ce qui se situe entre les balises HEAD soit (meta charset= »utf-8″)? J’ai enlevé les balises car le forum semble ne pas les accepter.
Voici où j’en suis des messages d’errreur :
Fatal error: Call to a member function on a non-object in /mnt/169/sdb/8/0/misstkali/WixMaxV3/espaceMembres/login.php on line 14
Ma ligne 14 contient :
$loginOK = $bdd->prepare(‘SELECT pass FROM membres WHERE mail = :mail’);
le charset dans le head ne changera pas l’encodage du fichier. C’est pour le navigateur le charset (et il doit correspondre à l’encodage du fichier évidement).
L’erreur est une erreur Php. Il faut voir du côté du code.
Bonjour Prélude
Alors pour ma part j’ai un souci assez régulier avec l’utf8 et l’insertion en base de données. Lorsque je conçois un site sur mon serveur local, j’ai pas de souci, mais quand je transfère le site sur le serveur client, les caractères accentués « é » sont remplacés par des « é », pourtant j’ai configuré pareil les tables : en utf8_general_ci. Est-ce que c’est du aussi au BOM, parce-que moi je n’ai pas de problème avec header(Location…)
Par contre espace est féminin en typographie, on dit/écrit donc une espace.
Bien cordialement.
Au temps pour moi, à force de chercher j’ai fini par trouver la réponse à mon problème : il faut renseigner le charset lors de la connexion à la base de données (charset=utf8). Chose que j’oubliais de faire systématiquement.