Cours PLURITAL 2013-2014

Cours n° 4 (12 novembre 2013)

Jean-François Perrot

Unicode

  1. Trois axes principaux
    1. Universalité
    2. Abandon de l'équation un caractère = un octet
    3. Une véritable élaboration théorique du concept de caractère

  2. Organisation du catalogue Unicode
    1. Plans et blocs
    2. Structure du BMP
    3. Vue d'ensemble
    4. Moyens exploratoires

  3. Promenade dans le catalogue Unicode

    1. Un coup d'œil aux plans supérieurs
      1. En Occident : le gotique
      2. Au Moyen-Orient : le vieux-perse
      3. En Extrême-Orient : l'écriture vietnamienne nôm

    2. Le plan multilingue de base (BMP)
      1. L'alphabet latin et ses extensions
      2. L'alphabet grec, ancien et moderne, et ses dérivés
      3. Les alphabets notant des langues sémitiques : arabe, syriaque, hébreu et éthiopien
      4. Les écritures indiennes
      5. Le cas du japonais
      6. Les caractères chinois et la question de la Han Unification

  4. Représentation en machine : généralités
    1. UTF-32, UTF-16, UTF-8
    2. Quel est le but poursuivi ? Travail local ou communication à distance ?

  5. UTF-8 : principe et mise en œuvre
    1. Principe
    2. Notation et expérimentation :
    3. Mise en œuvre



Résumé
: Qu'est-ce qu'Unicode ? (par lui-même) et Wikipedia (en anglais : la page française est plus développée, voir plus loin)

Références livresques :
Références en ligne :
  1. Trois axes principaux

    Le standard Unicode met en exergue 10 principes, dont l'exégèse ne manque pas d'intérêt
    (Desgraupes, chap. 1,  Haralambous, chap. 2).
    De notre point de vue d'utilisateurs, je retiens les trois points suivants :

    1. Universalité

      • Tous les systèmes d'écriture textuelle du monde (pas tous les répertoires de signes).
      • Convergence avec la norme ISO/IEC 10646.
      • Négociation permanente avec les instances réglementaires,
        mais le consortium reste fermement entre des mains américaines...
    2. Abandon de l'équation un caractère = un octet

      • Un total de 1 114 112 caractères potentiels (= 17 ×  65.536, soit 17 plans de 216 places chacun)
        En hexadécimal, de 0x000000 à 0x10FFFF.
        (Donc en principe 3 octets, mais les  ordinateurs ne raisonnent que par puissances de 2)

      • Pour la pratique courante le premier plan suffit ! Il s'appelle BMP = Basic Multilingual Plane
        Le BMP est caractérisé par le fait que les numéros Unicode correspondants tiennent dans deux octets.
        C'est heureux, car la plupart des langages de programmation qui fondent sur Unicode leur notion de caractère,
        à commencer par Java, se limitent à 16 bits - ce qui correspond à l'intention initiale !

      • Mais des domaines commencent à émerger où le recours aux plans supplémentaires s'impose.
        Nous en verrons un exemple avec le traitement des caractères nôm en vietnamien.

      • Plusieurs formats de représentation en machine employant de 1 à 4 octets.
    3. Une véritable élaboration théorique du concept de caractère

      • Un catalogue de caractères qui est une base de données accessible en ligne.
        Cette base est partagée en deux, la masse homogène des caractères chinois étant traitée à part.

      • Chaque caractère y est identifié par son numéro (en décimal ou en hexa -
        Desgraupes préfère employer le terme anglais code-point),
        et aussi par son nom (en anglais et en petites capitales - ne s'applique pas aux caractères chinois) :
        p. ex. n° 304 = x0130 LATIN CAPITAL LETTER I WITH DOT ABOVE

      • Ces données sont exploitées par des algorithmes complètement spécifiés dans la norme.

  2. Organisation du catalogue Unicode

  3. Promenade dans le catalogue Unicode

    Nous proposons ci-après une sélection de sujets qui nous intéressent particulièrement.
    Pour chacun d'entre eux, nous renvoyons aux pages d'Alan Wood qui traitent les différents blocs concernés.
    Si vous constatez que votre machine ne possède pas de police pouvant afficher les caractères en question,
    empressez-vous d'y remédier, en suivant les conseils d'Alan Wood !

  4. Représentation en machine : généralités

    1. UTF-32, UTF-16, UTF-8

      Une fois abandonnée l'équation un caractère = un octet, la question se pose du format de représentation.
      Pour des raisons historiques, les différents formats en usage portent le nom générique de UTF, abréviation de
      Unicode (ou Universal) Transfer (ou Transformation) Format.

      • Si on veut un format de taille fixe (nombre fixe d'octets pour chaque caractère),
        le seul choix compatible à la fois avec le nombre de caractères à représenter (1 114 112)
        et avec la technologie informatique est celui de 4 octets, ou 32 bits, appelé UTF-32.
        Il suffit d'écrire le numéro du caractère en tant que nombre entier sur 32 bits, donc (vu la taille de ce nombre)
        avec un premier octet nul dans tous les cas, et un second octet également nul pour tous les caractères
        du Basic Multilingual Plane.
        Ce procédé a l'avantage de la simplicité conceptuelle, et l'inconvénient de prendre de la place
        (4 fois plus qu'un codage sur 8 bits).

        Note : Le format UTF-32 est fort peu utilisé, à telle enseigne qu'un éditeur de textes assez perfectionné comme TextWrangler ne le propose pas dans sa liste de codes. Mais UnicodeChecker le donne !
        L'exemple suivant est donc fabriqué de toutes pièces, pour fixer les idées :

        Texte (le premier vers du deuxième quatrain des Poèmes sur le pêcher de Nguyễn Trãi, en nôm,
        choisi en raison de la présence de caractères en dehors du BMP - ici, en rouge):

        𠊚花窖𤇚精神 Tu déploies tout ton charme et les cœurs en sont troublés ;

        Octets

        000052D5 0002029A 000082B1 00007A96 000241DA 00007CBE 0000795E
        00000020 00000054 00000075 00000020 00000064 000000E9 00000070
        0000006C 0000006F 00000069 00000065 00000073 00000020 00000074
        0000006F 00000075 00000074 00000020 00000074 0000006F 0000006E
        00000020 00000063 00000068 00000061 00000072 0000006D 00000065
        00000020 00000065 00000074 00000020 0000006C 00000065 00000073
        00000020 00000063 00000153 00000075 00000072 00000073 00000020
        00000065 0000006E 00000020 00000073 0000006F 0000006E 00000074
        00000020 00000074 00000072 0000006F 00000075 00000062 0000006C
        000000E9 00000073 00000020 0000003B


        67 caractères, donc 67 mots de 4 octets = 268 octets.

      • Si on accepte un format de taille variable (nombre d'octets dépendant du caractère considéré),
        on a le choix entre un module de base de deux octets et un module de base d'un seul octet.

        1. Si on choisit un module de deux octets, soit 16 bits : UTF-16
          on utilise un seul module pour  tous les caractères du BMP,
          et deux modules (quatre octets) pour ceux des autres plans.

          Plus compliqué, mais plus économique en place que UTF32, surtout si on sort peu du BMP.

          Voici le même texte en UTF-16 big-endian (comme indiqué par le BOM FEFF en tête du fichier)

          FEFF 52D5 D840 DE9A 82B1 7A96 D850 DDDA 7CBE 795E
          0020 0054 0075 0020 0064 00E9 0070 006C 006F 0069
          0065 0073 0020 0074 006F 0075 0074 0020 0074 006F
          006E 0020 0063 0068 0061 0072 006D 0065 0020 0065
          0074 0020 006C 0065 0073 0020 0063 0153 0075 0072
          0073 0020 0065 006E 0020 0073 006F 006E 0074 0020
          0074 0072 006F 0075 0062 006C 00E9 0073 0020 003B


          67 caractères, donc 67 mots de 2 octets + 2 surrogates + 2 BOM = 140 octets.

        2. Si on choisit un module d'un octet, soit 8 bits : UTF-8
          on utilise un seul module pour les caractères ASCII (7 bits),
          et deux, trois ou quatre modules (octets) pour les autres.

          Nettement plus compliqué, mais encore plus économique en place,
          et surtout compatible avec l'ASCII !
          Tout fichier ne contenant que des caractères ASCII 7 bits est ipso facto un fichier UTF-8.
          Avantage considérable en pratique...

          Voici le même texte en UTF-8 (voir la section suivante pour explications)

          E58B95 F0A08A9A E88AB1 E7AA96 F0A4879A E7B2BE E7A59E
          20 54 75 20 64 C3A9 70 6C 6F 69 65 73 20 74 6F 75 74
          20 74 6F 6E 20 63 68 61 72 6D 65 20 65 74 20 6C 65 73
          20 63 C593 75 72 73 20 65 6E 20 73 6F 6E 74 20 74 72
          6F 75 62 6C C3A9 73 20 3B


          67 caractères, dont
          • 5 chinois du BMP, à 3 octets chacun = 15 octets,
          • 2 nôm du bloc CJK Ideograph Extension B, dans le deuxième plan supplémentaire,
            à 4 octets chacun = 8 octets,
          • 3 latins non-ASCII, à 2 octets la pièce = 6 octets,
          • 57 ASCII = 57 octets
          Total 15+8+6+57 = 86 octets.

    2. Quel est le but poursuivi ? Travail local ou communication à distance ?

      Il faut distinguer deux orientations dans la représentation des caractères Unicode en machine, selon le but poursuivi :
      • travail local (édition, au sens anglais du terme,
        ou plus généralement toute espèce de calcul sur le texte)
      • communication : réalisation d'un fichier qui sera envoyé à travers le réseau à d'autres machines.

      Ces deux ordres d'activité ne sont pas soumis aux mêmes contraintes techniques !
      • le travail local ne connaît à peu près aucune entrave, vu la puissance de calcul des machines modernes ;
      • la communication en revanche doit se préoccuper
        1. des différences de comportement entre machines (hétérogénéité des processeurs)
        2. des conventions en vigueur sur le réseau.

        1. L'hétérogénéité des processeurs se manifeste dans l'ordre de traitement des octets
          (processeurs gros-boutiens et petit-boutiens) ce qui oblige à des contorsions pour indiquer
          l'option choisie dans un fichier codé en UTF-16 ou en UTF-32 (à l'aide d'un BOM : Bit Order Mark).
          Par exemple, le logiciel de traitement de corpus Unitex travaille sur des fichiers codés en UTF-16 petit-boutien.

        2. Les conventions en vigueur visent les jeux de caractères exigés ou attendus par les
          différents protocoles de transmission (par exemple l'ASCII 7 bits pour le protocole SMTP).
          En ce qui nous concerne, le point important est le choix d'UTF-8 comme jeu de caractères par défaut
          dans le format XML.


        3. Il faut enfin observer que les attentes des logiciels de traitement ne sont pas toujours clairement exprimées.
          C'est le cas notamment pour les compilateurs et interprètes des langages de programmation.
          Par exemple, un programme Java contenant des lettres accentuées a des chances de ne pas s'exporter correctement
          d'une machine à l'autre - ce qui se comprend aisément.
          Le cas de JavaScript est très net : le code contenu dans les fichiers JavaScript (extension ".js") doit être écrit
          en ASCII pur (7 bits). Tout autre caractère doit être donné par son n° Unicode, sous la forme "\uHHHH"
          (voir plus loin).
          Il y a donc en fait deux genres de textes bien différents :
          1. les textes documentaires destinés à des lecteurs humains, par le truchement de logiciels comme les navigateurs Web,
            les éditeurs de textes ou les gestionnaires de courrier
          2. les textes-programmes destinés à des compilateurs et interprètes.
          Nous ne dirons rien de la seconde catégorie pour l'instant.

      Nous laisserons de côté les préoccupations relatives au travail local, en nous bornant à constater que
      les logiciels traitant des textes utilisent souvent UTF-16 ou UTF-32 pour représenter les caractères
      en mémoire centrale (buffer), et même, dans le cas d'Unitex, UTF-16 pour entreposer ses fichiers :
      si vous utilisez ce logiciel, il y a dans votre répertoire-maison (home directory) un répertoire nommé Unitex,
      dans lequel tous les fichiers sont codés en UTF-16 little-endian (UTF-16LE),
      allez les examiner avec votre éditeur hexadécimal favori !
      À titre de comparaison, voici ce que donne l'exemple précédent ainsi codé :

      FFFE D552 40D8 9ADE B182 967A 50D8 DADD BE7C 5E79
      2000 5400 7500 2000 6400 E900 7000 6C00 6F00 6900
      6500 7300 2000 7400 6F00 7500 7400 2000 7400 6F00
      6E00 2000 6300 6800 6100 7200 6D00 6500 2000 6500
      7400 2000 6C00 6500 7300 2000 6300 5301 7500 7200
      7300 2000 6500 6E00 2000 7300 6F00 6E00 7400 2000
      7400 7200 6F00 7500 6200 6C00 E900 7300 2000 3B00



      Pour en savoir plus sur ces codages, voyez Wikipedia en anglais
      (UTF-16, UTF-32).
      Nous nous concentrons ici sur les questions de communication, pour lesquelles UTF-8 est le codage
      de choix, en raison de sa diffusion croissante (tout Wikipedia !) et de sa compatibilité avec l'ASCII "pur".

  5. UTF-8 : principe et mise en œuvre

    1. Principe

      1. On part de l'idée de représenter les 128 premiers caractères (ASCII) sur un seul octet, comme par le passé.
        Ces octets ont comme caractéristique d'avoir un premier bit nul.

      2. Tous les autres caractères seront représentés par au moins deux octets.
        Il faut alors distinguer le premier octet du (ou des) octet(s) suivant(s).
        Ils ne peuvent pas commencer par "0" car c'est le privilège des octets ASCII.
        On décide que :
        • les octets suivants commenceront par "10"
        • le premier octet commencera par "110" ou par "1110" ou par "11110", etc,
          le nombre de "1" initiaux donnant le nombre total d'octets dans la représentation du caractère
          (en pratique, 2, 3 ou 4) .
        • Exemples :
          • sur trois octets 11100000 10100100 10001011 (en hexadécimal 0xE0A48B)
          • deux octets 11001110 10110001 (en hexadécimal 0xCEB1)
          • et sur un seul octet 01111000 (en hexadécimal 0x78, ASCII : on reconnaît la lettre minuscule "x")

      3. Ainsi, chacun des octets suivants peut porter 6 bits utiles (les 2 premiers étant fixés)
        tandis que le premier octet peut en porter 5, 4 ou 3, suivant le nombre de ses suivants.
        Avec ce système,
        • un code UTF-8 de deux octets porte 11 bits utiles (5+6),
          (suivant le "squelette" 110xxxxx 10yyyyyy - on note qu'en hexadécimal le premier octet commencera par C ou par D)
        • un code UTF-8 de trois octets porte 16 bits utiles (4+6+6),
          (suivant le "squelette" 1110xxxx 10yyyyyy 10zzzzzz - en hexadécimal le premier octet commencera par E)
        • et un code UTF-8 de quatre octets porte 21 bits utiles (3+6+6+6),
          (suivant le "squelette" 11110xxx 10yyyyyy 10zzzzzz 10tttttt - en hexadécimal le premier octet commencera par F)
        ce qui suffit largement pour les 17 plans Unicode.

      4. Pour déterminer le code UTF-8 d'un numéro Unicode donné, il suffit de :
        1. écrire ce numéro en binaire, et supprimer les zéros initiaux ;
          en fonction du nombre de bits utiles, déterminer le nombre d'octets UTF-8 ;
        2. décomposer le binaire de droite à gauche en tranches de 6 bits,
          plus une tranche de 5, 4 ou 3 (en complétant au besoin par des zéros à gauche) ;
        3. et "remplir" le squelette décrit ci-dessus en 3.

      5. Exemples :
        • DEVANAGARI LETTER VOCALIC R, n° 2315 = x090B
          en binaire 00001001 00001011, 12 bits utiles, il faut donc 3 octets UTF-8
          squelette  1110xxxx 10yyyyyy 10zzzzzz
          décomposition 4+6+6 : 0000 + 1001 00 + 00 1011
          résultat : 11100000 10100100 10001011, en hexa 0xE0A48B.

        • GREEK SMALL LETTER ALPHA, n° 945 = x03B1
          en binaire 00000011 10110001, 10 bits utiles, donc 2 octets UTF-8,
          squelette  110xxxxx 10yyyyyy
          décomposition 5+6 : 011 10 + 11 0001
          résultat : 11001110 10110001, en hexa 0xCEB1.

      6. Propriétés du codage UTF-8 :

        1. Le dernier chiffre hexadécimal du numéro Unicode d'un caractère se retrouve identique
          comme dernier chiffre de sa représentation en UTF-8.
          Ainsi le e accent aigu 'é', U+00E9, devient C3A9 en Unicode (comme vous l'avez vu lors du TD n°3)

        2. Plus le numéro Unicode est grand, plus le code UTF-8 correspondant, vu comme un nombre entier,
          est grand.
          En termes mathématiques, le codage UTF-8 est une application injective des entiers dans les entiers
          qui est croissante par rapport à l'ordre naturel.

        3. Conséquences pratiques
          • Les caractères de numéros inférieurs à 128 sont représentés en UTF-8 sur un octet (ASCII).

          • Ceux dont les numéros sont compris entre 128 et 2047 (= x07FF = 0000 0111 1111 1111),
            par deux octets :
            c'est le cas de toutes les versions de l'alphabet latin énumérées ci-dessus
            (donc de toutes nos "lettres accentuées"), du grec monotonique (mais pas polytonique),
            du cyrillique, de l'arménien (mais pas du géorgien),
            de l'hébreu et de l'arabe (mais pas de l'éthiopien).

          • Tout le reste du BMP (entre 2048 et  65535) est codé sur trois octets.
            Voyez par exemple le cas de l'écriture devanâgari.
            Ces triplets d'octets sont aisément reconnaissables sur un dump en hexadécimal,
            car le premier octet commence par "E" (en binaire 1110).
            Exemple : le caractère géorgien Ⴋ (U+10AB = GEORGIAN CAPITAL LETTER MAN), en UTF-8 0xE182AB.

          • Les caractères appartenant aux plans supérieurs sont codés sur quatre octets,
            avec un octet initial commençant par "F" (en binaire 1111).
            Exemple : le caractère gotique 𐌰 (U+10330 = GOTHIC LETTER AHSA), en UTF-8 0xF0908CB0.
    2. Notation et expérimentation :

      • Répétons qu'il faut bien distinguer

        1. la désignation du caractère (nommer le caractère)

          • par son n° (en décimal ou en hexa) suivant une syntaxe qui dépend du contexte :

            • dans le langage courant, on convient de désigner un carctère quelconque par une étiquette
              orthographiée U+lenumérohex plutôt que par son nom officiel, parfois très malcommode.
              Ainsi, on distinguera
              • Ά (alpha majuscule avec accent du grec moderne) qui est U+0391
              • de Ά (alpha majuscule avec accent aigu du grec ancien) qui est U+1FBB

            • en HTML/XML : &#lenumérodec; ou &#xlenumérohex;
              sont des entités permettant de désigner un caractère Unicode dans un contexte "tout ASCII".

              Ce procédé a l'avantage de ne rien supposer du côté du logiciel de traitement
              (voir ci-après les question de mise en œuvre d'UTF-8).
              Il est donc préféré des traditionnalistes attachés à iso-8859-1 !
              Pour l'observer, demandez à voir le code-source de la page.
              Exemple : un excellent site espagnol consacré à la culture arabe, en particulier à la poésie
              e.g. la page sur le poète préislamique عـنترة بن شداد

              Bien évidemment, son emploi systématique conduit à occuper beaucoup de place en mémoire
              (7 octets par caractère !). Mais des textes même substantiels ne pèsent rien à côté
              des mégaoctets exigés par les images ou par la vidéo !

            • en Java : '\ulenumérohex' est une constante de type char
              Attention ! le type primitif char est limité à la plage 0-6536 (2 octets),
              sa valeur maximale est donc '\uFFFF'.
              Réciproquement, tout entier de cette plage peut être affecté à une variable de type char,
              avec conversion automatique : si on exécute
              char x = 2315; char y = '\u090B';
              les deux variables x et y contiennent le même caractère
              (l'expression booléenne x==b vaut true).

            • en JavaScript (qui ne connaît pas les constantes de type caractère) :
              la forme \ulenumérohex peut (doit) être employée dans une constante de chaîne,
              et pour calculer on emploie la fonction chr appliquée au numéro
              vu comme une valeur entière (sur 16 bits !), fonction qui renvoie une chaîne monocaractère
              donc chr(lenumérodec) ou chr(0xlenumérohex)

            • Le problème des plans supplémentaires pour Java & JavaScript.
              Les caractères dont le numéro Unicode dépasse deux octets sont représentés comme
              des couples de pseudo-caractères (surrogates) dont chacun est codé sur 16 bits.
              Ce choix introduit quelques difficultés techniques, dont le détail diffère d'un langage à l'autre.
              Pour en savoir davantage...

            • en Perl : dans une constante de chaîne entre doubles-quotes : \x{lenumérohex},
              pour le BMP comme pour les plans supplémentaires,
              sans avoir à se préoccuper de la taille du nombre.


          • par son nom officiel (en Perl), à condition d'avoir effectué les réglages nécessaires..


          • Exemple : le caractère Unicode n° 304 = x0130 LATIN CAPITAL LETTER I WITH DOT ABOVE
            peut être désigné en HTML/XML par İ ou par İ, en Java par '\u0130'
            et en JavaScript par chr(304) ou par chr(0x130)

        2. sa réalisation matérielle
          laquelle prend deux aspects (dissymétriques) :

          • codage en octets (ici, UTF-8)
            Exemple : LATIN CAPITAL LETTER I WITH DOT ABOVE ==> sur 2 octets C4B0

          • affichage via une police (à condition qu'elle soit présente sur la machine !)
            Exemple : LATIN CAPITAL LETTER I WITH DOT ABOVE ==> İ

        Pour marquer cette distinction, nous écrirons désormais les octets des réalisations en UTF-8
        entre chevrons (comme ils sont produits par certains logiciels) :
        Exemple : LATIN CAPITAL LETTER I WITH DOT ABOVE ==> en UTF-8 sur 2 octets <C4><B0>

      • Exemple à bien comprendre : Voici le même texte
        Ça, c'est mon frère René et ça c'est ma sœur Iñès.
        d'abord en deux codages à 8 bits, Mac Roman et iso-8859-1 (Windows) :
        On peut constater que, dans les deux cas, les caractères non-ASCII sont représentés
        par un seul octet, mais qu'à chaque fois ce sont des octets différents !
        • <82>a, c'est mon fr<8F>re Ren<8E> et <8D>a c'est ma s<CF>ur I<96><8F>s.
        • <C7>a, c'est mon fr<E8>re Ren<E9> et <E7>a c'est ma s<9C>ur I<F1><E8>s.

        Et le voici en UTF-8, montrant clairement les deux octets nécessaires pour tout caractère non-ASCII :

        <C3><87>a, c'est mon fr<C3><A8>re Ren<C3><A9> et <C3><A7>a c'est ma s<C5><93>ur I<C3><B1><C3><A8>s.

      • Pour faciliter l'expérimentation, voici un outil qui vous permettra de confronter les différents aspects
        d'un caractère Unicode :
        1. son numéro que vous pouvez donner en décimal ou en hexa, et voir en binaire
        2. sa représentation UTF-8, en hexa (notation à chevrons) et en binaire
        3. son nom officiel (en lecture seule).
        Notez que les informations que vous tapez dans un des champs ouverts en écriture
        ne sont prises en compte que lorsque vous cliquez une première fois en dehors de ce champ.

        Le logiciel UnicodeChecker vous permettra de faire les mêmes expériences....
    3. Mise en œuvre

      Entrer & sortir :
      les machines modernes avec écran et clavier nous laissent croire que lire et écrire ne font qu'un
      c'est faux !
      L'écriture (fabrication d'un fichier) et la lecture (interprétation) sont deux processus dissymétriques.
      Cette dissymétrie est masquée par la puissance des machines et par la bonne adéquation des outils (clavier - écran - logiciels).
      Mais la puissance est relative et l'adéquation dépend du but poursuivi !

      • Côté entrée : deux étapes successives

        1. Écriture dans un outil d'édition par tout moyen à votre disposition
          (ils sont nombreux : menu d'insertion, donnée explicite du nom du caractère, clavier, palette, etc).
          • Note technique : cette écriture fait entrer les caractères dans le buffer de l'outil,
            qui loge en mémoire centrale en le recodant.
            Notez que l'utilisateur n'est en général pas informé de ce codage interne,
            (l'éditeur JEdit faisant exception : il déclare ouvertement
            que sa représentation interne est UTF-16).

        2. Sauvegarde dans un fichier sur disque en spécifiant le codage UTF-8.

          Notez que les modalités de cette spécification varient beaucoup avec le logiciel employé.
          Par exemple, sur Mac OS X :

          • L'éditeur de textes TextEdit répond à la commande Fichier>Enregistrer sous...
            par une fenêtre de dialogue où la question du codage est posée clairement.

          • L'éditeur HTML Netscape Composer en revanche distingue Fichier>Enregistrer sous...
            de Enregistrer en changeant de codage
            et il adopte un comportement diversifié suivant le choix de l'utilisateur.
            L'analyse de ce comportement n'est pas sans intérêt...

          • La version 1 de Microsoft Word pour Mac OS X (déjà ancienne) répond à la commande Fichier>Enregistrer sous...
            par une fenêtre de dialogue où la question du codage est posée comme cas particulier de modèle de document,
            le choix de Texte unicode conduisant à une sauvegarde en format texte UTF-16.

          • L'éditeur de textes JEdit distingue explicitement
            • le buffer en mémoire centrale (où les caractères sont représentés en UTF-16)
            • du fichier sur disque, dont le codage courant est affiché au bord inférieur de la fenêtre
              et peut être modifié par une commande adéquate (voir la documentation)

          Il convient donc de se renseigner soigneusement sur l'usage du logiciel employé,
          de préférence avant d'avoir à sauvegarder son travail en urgence,
          car un mauvais choix de codage peut conduire à la perte irrémédiable de l'information acquise...

      • Côté sortie : avertir le logiciel de traitement qu'il doit "lire" en UTF-8

        1. pour un éditeur prenant un fichier sur le disque,
          à l'ouverture du fichier (en général, codage par défaut donné dans les préférences de l'outil).
          Là aussi les mœurs des logiciels sont diverses, et il convient de chercher où l'information pertinente doit être fournie.
          Tous n'ont pas la limpidité de TextEdit...

        2. pour un logiciel recevant le fichier par le réseau,
          par un message spécifique avec un type MIME comme Content-Type: text/plain ou text/xml
          assorti de la mention "charset=UTF-8".
          C'est d'ordinaire le serveur de fichiers qui en a la charge, il est bon de contrôler son action.

          • Pour un courrier envoyé par SMTP, le logiciel émetteur devra envoyer un en-tête (header) :
            "Content-Type: text/plain; charset=UTF-8"

          • Pour un fichier HTML envoyé par un serveur Web comme Apache, c'est la déclaration du serveur
            qui a priorité. Tout dépend alors de sa configuration, qui peut fort bien imposer iso-8859-1
            (voir le cours 3). Si tel est le cas, il faut demander au responsable changer la directive en
            AddDefaultCharset Off.
            En supposant que le serveur soit muet sur ce point, l'auteur du fichier doit faire sa déclaration
            en ajoutant comme premier élément de la partie <head> de son fichier un élément ainsi conçu:
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            et en observant que tous les caractères précédents, à savoir <DOCTYPE....> <html xmlns:...><head>
            sont de l'ASCII 7 bits, donc déchiffrables sans ambiguïté.

          • Toujours en HTML, dans un formulaire (balise <form>) pour s'assurer que les chaînes tapées
            par l'utilisateur sont transmises au serveur en UTF-8 (et non pas selon la fantaisie du navigateur),
            il convient d'ajouter dans la balise l'attribut accept-charset="UTF-8".

          • Enfin, la norme HTML prévoit qu'un lien hypertexte peut porter un attribut charset
            destiné à informer le navigateur du jeu de caractères employé dans la page-cible (voyez ici)
            ce qui est fort utile lorsque le lien désigne une page en texte simple (ni HTML, ni XML),
            car en ce cas le navigateur applique son codage par défaut, qui est souvent Latin-1.
            Hélas, les navigateurs n'en ont cure... et il faut méditer la note de SelfHTML :
            "Il n'est pas établi si et comment un navigateur WWW affiche de telles mentions."
            C'est bien dommage !

          • En ce qui concerne les chaînes traitées, et notamment affichées, par JavaScript ou par Java,
            il convient de noter deux points :

            1. Pour JavaScript comme pour Java, tous les caractères d'une chaîne sont en Unicode .
              En particulier, la longueur d'une chaîne est le nombre de ses caractères et non pas
              celui de ses octets (sous réserve que ces caractères ne sortent pas du BMP).
              De même pour les fonctions d'accès charAt() et charCodeAt().
              JavaScript traitera donc correctement les chaînes que lui transmet le navigateur.
              Pour la communication avec ce dernier, voir ci-dessus.

            2. Le code JavaScript proprement dit (celui qui s'écrit dans les fichiers ".js" envoyés au
              navigateur en même temps que le HTML), comme il a été dit plus haut, doit être rédigé
              entièrement en ASCII, pour éviter les malentendus avec des navigateurs imprévisibles.
              Des caractères non-ASCII peuvent apparaître aussi bien dans les identificateurs
              que dans les constantes de chaînes, mais ils doivent ête donnés sous la forme
              "\ulenumérohex" comme en Java.
              On écrira par exemple, en supposant que la variable chn contient une chaîne :
              alert ('"'+ chn + '" ne repr\u00E9sente pas un nombre d\u00E9cimal !');
              pour obtenir :

              alert