Le codage des données numériques
09/02/2005
 Christian CALECA 
Liste des cours

Autres astuces

Accueil ] [ l'Ecriture ] [ Le code ASCII ] [ Autres astuces ] [ Dans le HTML ] [ MIME ]


Code toujours, tu m'intéresses

Par une remarquable tendance à la perversité de l'esprit humain, certains protocoles "applicatifs" (SMTP par exemple) ont été conçu avec comme axiome de départ qu'il devraient transporter du texte, alors qu'il est clair qu'ils n'auraient à transporter que des valeurs numériques binaires, puisqu'un système numérique ne sait finalement faire que cela.

D'ailleurs, le premier besoin qui s'est fait sentir, c'est de pouvoir attacher aux e-mails des fichiers qui sont tout, sauf du texte pur.

Pourquoi le parti pris du texte ?

A cause des caractères de contrôle !  C'est très pratique de disposer de caractères spéciaux qui permettent, comme leur nom l'indique, de contrôler le flux de données. Avec le codage ASCII, nous avons vu qu'il en existait pas mal, même si nous ne sommes pas entrés dans le détail de leur signification.

De plus, nous n'avons pas parlé du codage des valeurs numériques. Si un nombre entier ne pose pas trop de problèmes (1, 2 octets ou plus, éventuellement, encore que reste à savoir dans quel ordre on va les passer), les nombres réels, codés sous la forme mantisse / exposant sont un réel casse-tête. Un exemple faux mais qui fait comprendre : Le nombre 1 245 389 789 726 986 425 ne va pas s'utiliser ainsi, on va d'abord l'écrire, par exemple sous la forme 1245,389789726986425 10 15. On s'attachera alors à stocker en mémoire ce réel sous une forme approchée en utilisant systématiquement, disons trois octets. Sa partie entière, 1245 dans l'exemple, sera codée sur deux octets et la puissance de 10, 15 dans l'exemple, sur un octet. 

Cet exemple n'a pas de réalité, mais le principe est à peu près juste. Suivant les plateformes et les langages de programmation, nous aurons nos réels stockés  sur 4, 6 ou 8 octets, avec plus ou moins de précision sur la mantisse, ou plus ou moins d'espace sur la puissance de 10, suivant la nature des calculs à réaliser (aviez-vous pensé que la notion d'infini ne peut être gérée par un calculateur ?). Au final, il est souvent plus simple de communiquer des valeurs numériques à un tiers sous leur forme ASCII (telles qu'on peut les afficher ou les imprimer, avec des symboles d'écriture, donc), plutôt que telles qu'elles sont stockées en mémoire.

La conséquence ?

Ces protocoles ne peuvent pas simplement transférer des données numériques, puisqu'un octet est à priori considéré comme l'image d'un caractère et non comme une donnée numérique en elle même. Ainsi, si vous voulez transférer un fichier qui contient une représentation "bitmap" d'une image, comme un fichier jpeg, png ou gif, par exemple, vous ne pouvez pas considérer que c'est du texte, puisque à priori, chaque octet peut prendre n'importe quelle valeur, y compris celle d'un caractère de contrôle. Vous connaissez beaucoup de pages Web sans aucune image dedans ? Vous n'avez jamais envoyé un e-mail avec une image en pièce jointe ?

La conclusion est qu'il a fallu trouver une astuce pour transporter des données purement numériques sur un protocole qui n'est pas prévu pour ça.

Codage à tous les étages

Le jeu va consister maintenant à coder une donnée purement numérique sous une forme alphabétique, elle-même codée sur des valeurs numériques, pour qu'elle puisse être transportée sur un système qui ne connaît que des 0 et des 1. 

Tordu, n'est-ce pas ?

Oui, mais comment faire autrement ? Les révolutions, c'est bien, mais on ne peut pas en faire tous les jours, sinon, c'est le chaos permanent. Vous allez voir que les solutions apportées sont certes parfois tordues, mais astucieuses et surtout efficaces.

Comme il est clair, à la lueur de ce que nous avons vu jusqu'ici, que la seule convention qui soit à peu près universellement acceptée et correctement transportée par les protocoles applicatifs est la norme iso-646 (US-ASCII), il faudra trouver des conventions de codage  pour convertir un octet en un ensemble de caractères sur 7 bits.

C'est parti pour la grande cuisine.

Le codage "quoted printable"

Ce codage est principalement employé pour transformer un texte écrit avec un codage sur 8 bits en un texte qui ne contiendra que des caractères codables sur 7 bits. Vous allez voir comme c'est simple :

D'abord, il faut savoir sur quel codage 8 bits on va s'appuyer, en général, pour nous, iso-8859-1.

Ensuite, nous allons utiliser un "code d'échappement" (c'est une technique assez courante, nous la rencontrons  souvent en informatique). Ici, le caractère d'échappement est le signe =. Ce signe signifie que les deux caractères qui vont le suivre représenteront le code hexadécimal d'un caractère et non le caractère lui-même. Bien entendu, il faudra aussi coder le caractère d'échappement.

Un petit exemple vaudra bien mieux qu'un long discours... 

L'expression çà et là sera donc transmise sous la forme =E7=E0 et l=E0

Ainsi, nous transporterons nos données uniquement sous la forme de caractères US-ASCII (7 bits), même s'ils nécessitent 8 bits pour être définis.  En effet, les caractères =, E, et 0 ont tous des codes ASCII sur 7 bits.

Astucieux non ?

Bien entendu, il vaut mieux le savoir pour décoder correctement le message. Cette méthode est utilisée principalement pour les e-mails. En voici un exemple :

Return-Path: <christian.caleca@free.fr>
...
From: "Christian Caleca" <christian.caleca@free.fr>
To: <christian.caleca@free.fr>
Subject: quoted
Date: Tue, 5 Nov 2002 10:51:34 +0100
MIME-Version: 1.0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
...
X-Mailer: Microsoft Outlook Express 6.00.2800.1106
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106

=E7=E0 et l=E0

Notez que l'on parle ici de MIME, en indiquant, la nature du contenu (text/plain), le jeu de caractères utilisé (iso-8859-1) et le mode d'encodage : quoted-printable.  Nous y reviendrons plus tard.

Le codage Base64

Plus généralement, ce codage permettra de passer non seulement du texte codé sur 8 bits, mais aussi tout type de données constituées d'octets. Voyons d'abord avec du texte.

Là aussi, il faudra commencer par indiquer en quel code est écrit le texte initial. Pour nous, toujours iso-8859-1.

Trois caractères de 8 bits (24 bits au total) sont découpés sous la forme de 4 paquets de 6 bits (toujours 24 bits au total). Chaque valeur sur 6 bits, comprise donc entre 0 et 3F en hexadécimal, sera symbolisée par un caractère présent, et avec le même code, dans toutes les versions de code ASCII et EBCDIC.  La table d'équivalence est celle qui suit. Remarquez que les caractères choisis sont tous codés sur 7 bits en US-ASCII, mais que la valeur qu'ils représentent n'est pas leur code ASCII

dec hex car.   dec hex car.   dec hex car.   dec hex car.
0 0 A 16 10 Q 32 20 g 48 30 w
1 1 B 17 11 R 33 21 h 49 31 x
2 2 C 18 12 S 34 22 i 50 32 y
3 3 D 19 13 T 35 23 j 51 33 z
4 4 E 20 14 U 36 24 k 52 34 0
5 5 F 21 15 V 37 25 l 53 35 1
6 6 G 22 16 W 38 26 m 54 36 2
7 7 H 23 17 X 39 27 n 55 37 3
8 8 I 24 18 Y 40 28 o 56 38 4
9 9 J 25 19 Z 41 29 p 57 39 5
10 A K 26 1A a 42 2A q 58 3A 6
11 B L 27 1B b 43 2B r 59 3B 7
12 C M 28 1C c 44 2C s 60 3C 8
13 D N 29 1D d 45 2D t 61 3D 9
14 E O 30 1E e 46 2E u 62 3E +
15 F P 31 1F f 47 2F v 63 3F /
 

Comme cette explication doit paraître fumeuse à plus d'un (moi-même, plus je la relis, plus je la trouve fumeuse), là encore, prenons un exemple. Soit à coder le texte extrêmement simple  : 012

Ce texte est destiné à être écrit avec un codage iso-8859-1. 

caractère initial 0 1 2
Code ASCII hexa 30 31 32
Code ASCII binaire 00110000 00110001 00110010

Bien. nous avons donc la suite de 24 bits suivante : 001100000011000100110010. Nous allons maintenant la couper en quatre morceaux de 6 bits :

les valeurs sur 6 bits 001100 000011 000100 110010 
Equivalent hexadécimal 0C 03 04 32
Caractère équivalent en  Base64 M D E y

Et voilà. 012 donne, une fois codé en Base 64 MDEy. Constatez comme c'est simple. Constatez surtout que ces caractères seront transcrits en US-ASCII, donc sur 7 bits. 

Pour décoder, il suffit de le faire dans l'autre sens.

Refaisons la manip avec un e-mail codé en Base64 :

Return-Path: <christian.caleca@free.fr>
...
From: "Christian Caleca" <christian.caleca@free.fr>
To: <christian.caleca@free.fr>
Subject: Base 64 (1)
Date: Tue, 5 Nov 2002 11:07:11 +0100
MIME-Version: 1.0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: base64
...
X-Mailer: Microsoft Outlook Express 6.00.2800.1106
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106

MDEy

Et voilà le travail.

Ca, c'est une démo "commerciale", c'est à dire "qui ne montre que ce qui est facile et qui marche bien". Vos messages contiennent tous un nombre de caractères qui est un exact multiple de 3 ?

Dans ce cas (nombre de caractères qui n'est pas un multiple de 3) , le système de codage va "remplir le trou" avec un caractère spécial, qui ne sera pas interprété à l'arrivée. Ce caractère est le signe =

Voyons ce que ça donne si le texte initial ne contient plus que le seul caractère 0.

Au total, on aura MA==

Vérification par l'e-mail :

Return-Path: <christian.caleca@free.fr>
...
From: "Christian Caleca" <christian.caleca@free.fr>
To: <christian.caleca@free.fr>
Subject: base 64 (3)
Date: Tue, 5 Nov 2002 11:18:06 +0100
MIME-Version: 1.0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: base64
...
X-Mailer: Microsoft Outlook Express 6.00.2800.1106
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106

MA==

CQFD.

Et les autres...

uuencode

Bien entendu, d'autres conventions existent, mais n'appartiennent pas aux système MIME. Par exemple UUENCODE, assez proche de Base64, mais antérieur, utilisé sur plateformes Unix.

BinHex

Un codage propriétaire, créé dans le monde Macintosh pour les mêmes raisons...

Vous le voyez, les astuces ne manquent pas pour utiliser exclusivement de l'ASCII 7 bits dans le transport de n'importe quelle donnée.

Conclusions

En plus du codage des caractères dans des tables de 7 , 8 ou même 16 bits, il faut donc ajouter des systèmes qui vont s'efforcer de représenter tout type de donnée sous forme de texte 7 bits.

Ceci nous amène naturellement à parler de MIME...


Précédente ] [ Accueil ] [ Suivante ]