Unicode et UTF8

Codage des caractères (code UNICODE) puis encodage du code Unicode (UTF-8)

Voici une phrase en Grec ancien qui signifie "les animaux courent"

Τἁ ζῷα τρἐχει

Questions

  1. Faire un clic droit pour faire afficher le code source de la page et vous pouvez voir qu'à chaque caractère est associé un nombre hexadécimal. Quel est le nombre hexadécimal associé à ζ ?
  2. Voir ici le site de l'organisme qui gère l'Unicode et allez à Greek pour retrouver le nombre hexadécimal qui code ζ
  3. Sur combien d'octets sera codé ce caractère ?
  4. Va-t-on ensuite juxtaposer les codes Unicode pour coder les chaînes de caractères ?

    Lire le document suivant pour répondre à la question précédente

Que retenir ?

  1. En Python 3 le type string (chaîne de caractères) est codé en Unicode,à chaque caractère est associé un code, un entier en hexadécimal, par exemple la lettre a a pour code U+61 (en hexadécimal 61), le chiffre 1 a pour code U+31

    Ce que l'on nomme Basic Latin est codé de 0x00 à 0x7F (128) et correspond ce qui anciennement s'appelait le code ASCII

    D'autres codes: comme é -> 0xE9, œ -> 0x0153 (deux octets),β -> 0x03b1 (deux octets),π -> 0x03C0 , l' équivalent du d en russe la lettre д a pour code en hexadécimal 0x0434

    Voici un exemple sur 3 octets 𝔐 -> 0x1D510

  2. En machine il n' y a que des octets, et la transformation du code Unicode en octets, s'appelle l'encodage

    L'encodage le plus utilisé de par le monde est à l'heure actuelle l'UTF-8 (pour Unicode Transformation Format) et 8 pour octets

    Concrètement si le code du caractère est < 128, l' encodage se fait sur un octet celui du code

    Sinon l'encodage donnera une séquence de deux, trois ou quatre octets éventuellement par la transformation suivante:

UTF 8 et fonctions natives de Python

Il s'agit de vérifier à partir de fonctions Python le "hack" de l'utf-8

  1. Regardons le cas de la lettre Δ dont le code Unicode est U+0394
  2. En tapant dans l'interpréteur Python s = chr(0x394) le caractère Δ est affecté à s
  3. Si on veut les octets (bytes) on utilise la commande s.encode() et on obtient deux octets sous la forme b'\xce\x94'
  4. Vérifions que 0xce94 correspond bien à l'encodage utf-8 pour le code de 2 octets 0x394

    Convertissons le code Unicode hexadécimal 0x0394 sous la forme de deux octets, on obtient 00000011 10010100 (on fait bin(int(0x0394,16)))

  5. On forme le premier octet en ajoutant après la séquence 110 les trois derniers bits de 00000011 et les deux premiers de 10010100, donc on obtient

    11001110 qui en hexadécimal est 0xce

    Le deuxième octet commence par 10 avec à la suite les bits restants du deuxième octet du code c'est à dire:

    10010100 qui en hexadécimal est 0x94

  6. Comment fait on alors pour ne pas se tromper dans l'opération inverse de décodage ?

    Pourquoi ne peut on pas se tromper s'il faut décoder 11001110 10010100 01111000 ? Pourquoi on ne peut obtenir que Δx ?

    Lorsqu'on lit un octet les premiers bits sont significatifs, on enlève de l'octet les éventuels 1 et le premier zéro, le nombre de 1 obtenus renseigne sur les octets qu'il faudra traiter ensemble, ainsi dans notre exemple 110 signifie qu'il faut traiter les deux octets 11001110 et 10010100 ensemble

    Un octet seul commence toujours par 0, si un octet commence par 10, c'est qu'il fait partie d'un groupe de 2, 3 ou 4 octets

    Il faut regarder un des octets qui le précédent pour avoir le nombre d'octets du groupe :

    110 -> 2 octets, 1110 -> 3 octets, 11110 -> 4 octets

    Pour voir si vous avez compris trouver l'encodage en UTF 8 du caractère ζ