Unicode

Codage des caractères

Voir ici un survol historique du codage des caractères

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 codages: 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

    Beaucoup d'autres exemples ici

  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:

Unicode et fonction built-in 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 que 0x0394 -> 0xce94 correspond bien à l'encodage utf-8 pour un code de 2 octets:

    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

Exercice

  1. Pour chaque chaîne de caractères suivantes donner pour chaque caractère le code Unicode puis encoder la chaîne en UTF-8

    • s = "ΔÎ"
    • s = "Δ = B^2 -4AC"
  2. Construire une fonction decode(listeOctets) qui retourne une liste de nombres hexadécimaux chaque nombre étant le code Unicode d'un caractère