IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Voir le flux RSS

Pierre Fauconnier

Convertir une chaine en utf-8

Noter ce billet
par , 04/10/2021 à 08h00 (2705 Affichages)
Salut.

Dans un précédent billet, je vous racontais l'histoire de Unicode et utf-8. Pour rappel, Unicode est une page de code universelle qui a pour ambition de reprendre tous les caractères et symboles utilisés sur la planète et de leur donner un code unique, compréhensible par tous les systèmes informatiques utilisant la norme. Quant à utf-8, c'est une manière de coder une chaine en Unicode pour la transférer d'un système à l'autre.

Mise en situation

Dernièrement, j'ai dû récupérer des données d'un site web via une api Swagger (https://swagger.io/). Cette api permet d'échanger avec un site web au travers de requêtes GET ou POST. En lecture, elle renvoie un json contenant les données que la requête a permis de récupérer. C'est un très bon outil que je rencontre pour la deuxième fois lors d'un développement. Il m'a notamment amené à créer un parseur json en VBA qui donne satisfaction au client.

Swagger permet aussi d'envoyer des données sur un site Web, de sorte que c'est un sas d'échange d'information entre une application Web et une application tierce.

MAIS!!! Tant en lecture qu'en écriture, les json sont codés en UTF-8. C'est assez logique dans la mesure où c'est le codage de texte habituel du web. Jusqu'ici, pour la deuxième application que je code avec Swagger, je n'ai pas réussi à déterminer correctement l'entête (le header html) pour spécifier à mon HtmlRequest que je recevais de l'UTF-8. Je me ramasse donc le codage UTF-8 des caractères accentués, du symbole €, etc... Pas très drôle.

Le texte Je voudrais un café s'il vous plait. Ça vous fera 4€, Monsieur sera récupéré comme étant Je voudrais un café s'il vous plait. Ça vous fera 4€, Monsieur. C'est bof bof, comme on dit chez moi! Si je dois envoyer ce texte sur le site web, je vais pourtant devoir envoyer le second texte, car le premier ne passera pas correctement au niveau de certains caractères.

A ma connaissance, il n'existe pas de fonction native en VBA pour passer de ascii à utf-8 ni de utf-8 à ascii. Lors de l'écriture dans un fichier texte qui doit être en utf-8:
  • On pourrait passer par un stream adodb, mais il faut connaître la technique;
  • On pourrait bien sûr créer une fonction qui réalise l'opération avec ADODB et la stocker dans un module Tools (voir ce billet à propos du module Tools) de manière à pouvoir faire abstraction de la technique en utilisant une fonction qui l'encapsule;
  • On pourrait passer par une table de mappage (un tableau de conversion) qui reprendrait les caractères problématiques dans une colonne et leur conversion en utf-8 dans l'autre. On pourrait alors réaliser un remplacement de chaque caractère du tableau au sein du texte à convertir. Le problème, c'est qu'il ne faut pas en oublier. Ca ne se limite pas aux caractères accentués, mais en fait à tous les caractères dont le code ascii est supérieur à 127. Je devrais donc avoir un tableau (en Excel ou mieux, en VBA si je veux pouvoir l'utiliser avec d'autres technos telles que Word, par exemple) reprenant les 128 caractères >127 de notre page de code pour les "mapper" en utf-8;
  • On pourrait aussi créer nos propres fonctions de conversion.



Yeah. Ça, ça me botte, la fonction de conversion! Allons-y.


Un peu de théorie

Comme on la vu dans le billet sur l'histoire (très synthétique) de Unicode, cette page de code recense un nombre impressionnant de caractères (+ de 140 000 à l'heure actuelle) qui ne peuvent pas être codés sur un octet (256 caractères). 3 octets sont nécessaires pour l'opération. Dans la mesure où il y en a plus que 131 072 (2^17), 4 octets sont même nécessaire pour certains caractères, vu la manière de coder utilisée en utf-8.

L'idée derrière utf-8 est de coder les caractères sur le moins d'octets possibles. Pour rappel, la lettre A possède le code 65dec (01000001bin) et tient donc sur 1 octet, alors qu'en Unicode, on devrait la faire tenir sur 3 (00000000 00000000 01000001bin). On va donc partir de la règle suivante:
  • Un caractères dont l'unicode est <128 est transféré en 1 octet;
  • Un caractère dont l'unicode est >127 et <2048 est transféré sur 2 octets;
  • Un caractère dont l'unicode est >2047 et <65536 est transféré sur 3 octets;
  • Un caractère dont l'unicode est >65535 est codé sur 4 octets.


Mais comment coder et pourquoi ces limites (128, 2048, 65536)?

L'idée est d'utiliser aussi peu d'octets que possible. Les caractères dont le code est inférieur à 128 ont forcément leur bit de poids fort à 0. On va coder ces caractères sur un seul octet. Au décodage, lorsque l'on tombera sur un octet dont le bit de poids fort sera 0, on saura qu'il concerne un caractère codé sur un octet.

Pour les caractères "composés", c'est-à-dire qui tiennent sur plusieurs octets, la règle est la suivante:
  • Le premier octet contient autant de bits de poids fort à 1 qu'il y a d'octets puis un bit à 0;
  • les autres octets ont le bit de poids fort à 1 et le second bit de poids fort à 0.



Concrètement, ça donne ceci:
  1. un seul octet => 0xxxxxxx (7 bits pour le code);
  2. deux octets => 110xxxxx 10xxxxxx (11 bits pour le code);
  3. trois octets => 1110xxxx 10xxxxxx 10xxxxxx (16 bits pour le code);
  4. quatre octets => 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx (21bits pour le code).



On comprend dès lors mieux les limites exprimées plus haut:
  1. 1 octet, 7 bits pour le code en lui-même, valeur maximum 2^7 -1 = 127 (01111111bin);
  2. 2 octets, 11 bits pour le code, valeur maximum 2^11 -1= 2 047 = (11011111 10111111bin);
  3. 3 octets, 16 bits pour le code, valeur maximum 2^16 -1 = 65 535 (11101111 10111111 10111111bin);
  4. 4 octets, 21 bits pour le code, valeur maximum 2^21-1 = 2 097 152 (11110111 10111111 10111111 10111111bin).


Voici un tableau qui illustre comment on passe de la valeur unicode au codage utf-8
Nom : 2021-10-04_082049.png
Affichages : 908
Taille : 13,0 Ko


Conclusions

Voici pour la partie théorique. On comprend maintenant mieux que utf-8 permet de coder une chaine Unicode en consommant un minimum d'octets. Notre chaine Je voudrais un café s'il vous plait. Ça vous fera 4€, Monsieur qui compte 62 caractères va à peine grossir en passant en utf8 et donc en devenant Je voudrais un café s'il vous plait. Ça vous fera 4€, Monsieur (66 "caractères").

Dans un prochain billet, on traduira cela en fonctions VBA en jouant avec les bits...

Envoyer le billet « Convertir une chaine en utf-8 » dans le blog Viadeo Envoyer le billet « Convertir une chaine en utf-8 » dans le blog Twitter Envoyer le billet « Convertir une chaine en utf-8 » dans le blog Google Envoyer le billet « Convertir une chaine en utf-8 » dans le blog Facebook Envoyer le billet « Convertir une chaine en utf-8 » dans le blog Digg Envoyer le billet « Convertir une chaine en utf-8 » dans le blog Delicious Envoyer le billet « Convertir une chaine en utf-8 » dans le blog MySpace Envoyer le billet « Convertir une chaine en utf-8 » dans le blog Yahoo

Mis à jour 04/10/2021 à 08h22 par Pierre Fauconnier

Catégories
VBA , MS Office , Trucs & Astuces

Commentaires