CodeGym /Cours /JAVA 25 SELF /Jeux de caractères essentiels : UTF-8, UTF-16, ISO-8...

Jeux de caractères essentiels : UTF-8, UTF-16, ISO-8859-1

JAVA 25 SELF
Niveau 37 , Leçon 1
Disponible

1. UTF-8 — le roi des encodages modernes

Dans votre travail de programmeur, vous rencontrerez des fichiers, des protocoles réseau, des bases de données, des services Web, où différents encodages sont utilisés. Si vous ne savez pas en quoi UTF-8 diffère de ISO-8859-1, vous tomberez facilement dans un piège : votre code fonctionnera « chez moi », mais se cassera chez un collègue en France ou dans le cloud, où le système par défaut est différent.

Aujourd’hui, nous allons examiner trois encodages principaux que rencontre un développeur Java dans la vie réelle :

  • UTF-8 — standard universel moderne.
  • UTF-16 — format interne des chaînes en Java et souvent présent sous Windows.
  • ISO-8859-1 (Latin-1) — ancien, mais encore rencontré, encodage monooctet pour les langues d’Europe occidentale.

Découvrons-les de plus près !

De quoi s’agit‑il ?

UTF-8 (Unicode Transformation Format, 8-bit) est un encodage capable de représenter n’importe quel caractère de l’immense table Unicode (c’est-à-dire la cyrillique, les sinogrammes chinois, les émojis, et même des écritures anciennes rares). Et il le fait de façon astucieuse : pour les caractères les plus fréquents (lettres anglaises, chiffres, ponctuation), il n’utilise que 1 octet. Pour les autres — 2, 3 ou même 4 octets.

Fait : Tous les sites modernes, la plupart des fichiers JSON et XML, et même les sources Java utilisent par défaut UTF-8.

Combien d’octets pour un caractère ?

  • Caractères ASCII (lettres anglaises, chiffres, ponctuation) — 1 octet.
  • Caractères cyrilliques, caractères européens avec diacritiques2 octets.
  • Idéogrammes chinois, japonais et coréens3 octets.
  • Très exotiques, émojis4 octets.

Exemple :

Symbole Code Unicode UTF-8 (en octets)
A
U+0041
41
Ya
U+042F
D0 AF
U+20AC
E2 82 AC
😀
U+1F600
F0 9F 98 80

Pourquoi UTF-8, c’est génial ?

  • Rétrocompatible avec ASCII : si le fichier ne contient que des caractères anglais, il est strictement identique à ASCII.
  • Compacité : pour de courts textes en anglais, un fichier en UTF-8 sera de taille minimale.
  • International : prend en charge toutes les langues du monde, y compris les émojis.
  • Standard du Web : HTML, CSS, JSON, XML, JavaScript — tout cela est par défaut en UTF-8.

Exemple d’utilisation en Java

import java.nio.charset.StandardCharsets;
import java.nio.file.*;

public class Utf8Demo {
    public static void main(String[] args) throws Exception {
        // Écriture d'une chaîne dans un fichier en UTF-8
        String text = "Bonjour, le monde ! 😀";
        Files.write(Paths.get("utf8.txt"), text.getBytes(StandardCharsets.UTF_8));

        // Lecture du fichier en UTF-8
        String read = Files.readString(Paths.get("utf8.txt"), StandardCharsets.UTF_8);
        System.out.println(read); // Affichera : Bonjour, le monde ! 😀
    }
}

Ici, nous encodons d’abord explicitement la chaîne en UTF-8 avant l’écriture, puis nous indiquons explicitement le même encodage à la lecture. Grâce à cela, le texte est conservé et restauré sans distorsion, même s’il contient des émojis ou des caractères de différentes langues.

Quand utiliser UTF-8 ?

Toujours, sauf si vous avez une raison vraiment impérieuse d’en choisir un autre. C’est le choix universel pour toutes les applications modernes.

2. UTF-16 — le format interne de Java

UTF-16 est un autre encodage de la famille Unicode. Contrairement à UTF-8, il utilise le plus souvent 2 octets par caractère. C’est ainsi que Java stocke les chaînes (String) et les caractères (char) dans la JVM. Mais il y a un bémol : certains caractères (par exemple des idéogrammes rares ou des émojis) requièrent 4 octets (deux « paires de substitution »).

Où utilise‑t‑on UTF-16 ?

  • À l’intérieur de Java : toutes les chaînes et caractères — c’est du UTF-16.
  • Windows : de nombreux fichiers système sous Windows utilisent UTF-16 (par exemple, Notepad enregistre par défaut en UTF-16 LE).
  • Certains protocoles et formats : par exemple, XML peut être en UTF-16.

Exemple : à quoi ressemble une chaîne en UTF-16

Symbole Code Unicode UTF-16 (octets) Commentaire
A
U+0041
00 41
2 octets
Ya
U+042F
04 2F
2 octets
U+20AC
20 AC
2 octets
😀
U+1F600
D8 3D DE 00
4 octets (paire de substitution)

Exemple d’utilisation en Java

import java.nio.charset.StandardCharsets;
import java.nio.file.*;

public class Utf16Demo {
    public static void main(String[] args) throws Exception {
        String text = "Bonjour, le monde ! 😀";

        // Écriture de la chaîne dans un fichier en UTF-16
        Files.write(Paths.get("utf16.txt"), text.getBytes(StandardCharsets.UTF_16));

        // Lecture du contenu du fichier en UTF-16
        String read = Files.readString(Paths.get("utf16.txt"), StandardCharsets.UTF_16);
        System.out.println(read); // Affichage correct de la chaîne d'origine
    }
}

Point clé : à l’écriture et à la lecture, vous devez indiquer le même encodage. Si vous écrivez en UTF-16 et lisez par défaut (par exemple en UTF-8), vous obtiendrez une « bouillie » de caractères.

Particularités d’UTF-16

  • Longueur fixe pour la plupart des caractères : 2 octets.
  • Paires de substitution : certains caractères (par exemple les émojis) nécessitent 4 octets.
  • Byte Order Mark (BOM) : on ajoute souvent au début du fichier un « header » spécial indiquant l’ordre des octets (LE — little endian, BE — big endian). Java reconnaît généralement le BOM automatiquement.
  • Non compatible avec ASCII : si vous ouvrez un fichier UTF-16 dans un éditeur qui attend ASCII ou UTF-8, vous verrez une multitude de zéros et de signes étranges.

Quand utiliser UTF-16 ?

  • Si vous travaillez avec des systèmes ou fichiers très spécifiques qui exigent précisément UTF-16 (par exemple, intégration avec des applications Windows).
  • Pour les applications et fichiers ordinaires — préférez UTF-8.

4. ISO-8859-1 (Latin-1) — un vestige du passé

ISO-8859-1, ou Latin-1, est un encodage monooctet créé dans les années 80. Il prend en charge 256 caractères : alphabet anglais, lettres d’Europe occidentale avec diacritiques (é, ü, ç, etc.), signes de ponctuation, caractères spéciaux.

Fait : Cet encodage n’inclut pas la cyrillique, le grec, l’arabe, le chinois, ni d’autres écritures non latines.

Où rencontre‑t‑on ISO-8859-1 ?

  • Dans d’anciens fichiers et programmes (surtout en Europe).
  • Dans certaines bases de données et certains protocoles « par défaut ».
  • Dans les en-têtes HTTP (selon la norme, des données textuelles sans encodage explicite sont considérées comme ISO-8859-1, bien que dans la pratique ce soit rare).

Exemple : à quoi ressemble une chaîne en ISO-8859-1

Symbole Code Unicode ISO-8859-1 (octet) Commentaire
A
U+0041
41
Identique à ASCII
é
U+00E9
E9
Français
ü
U+00FC
FC
Allemand
Ya
U+042F
Caractère inexistant !

Exemple d’utilisation en Java

import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.nio.charset.Charset;

public class Latin1Demo {
    public static void main(String[] args) throws Exception {
        String text = "Bonjour, ça va? Café!"; // Texte français
        Files.write(Paths.get("latin1.txt"), text.getBytes(StandardCharsets.ISO_8859_1));

        // Lecture du fichier en ISO-8859-1
        String read = Files.readString(Paths.get("latin1.txt"), StandardCharsets.ISO_8859_1);
        System.out.println(read); // Tout se lit correctement !

        // Essayons d'écrire du texte cyrillique
        String cyrillic = "Bonjour, le monde !";
        try {
            Files.write(Paths.get("badlatin1.txt"), cyrillic.getBytes(StandardCharsets.ISO_8859_1));
        } catch (Exception e) {
            System.out.println("Erreur : impossible d'écrire de la cyrillique en ISO-8859-1 !");
        }
    }
}

L’encodage ISO-8859-1 (Latin-1) ne prend en charge que les caractères d’Europe occidentale — par exemple, les lettres accentuées du français, de l’allemand ou de l’espagnol. Ainsi, un texte français s’enregistre et se lit sans problème.

Cependant, la cyrillique est absente de cet encodage, et une tentative d’enregistrer un tel texte entraîne une erreur ou une perte de caractères. C’est pourquoi, pour des textes multilingues, il vaut mieux utiliser UTF-8 ou UTF-16, qui couvrent un ensemble de caractères bien plus vaste.

Particularités d’ISO-8859-1

  • Limitation par langues : uniquement les langues d’Europe occidentale.
  • 1 octet par caractère : compact, mais très limité.
  • Enregistrer des caractères « étrangers » provoque des altérations : si vous tentez de sauvegarder de la cyrillique ou des idéogrammes, ils se transformeront en points d’interrogation ou en « bruit ».

Quand utiliser ISO-8859-1 ?

  • Uniquement si vous vous intégrez à un système ou une base de données très ancien(ne) qui exige cet encodage précis.
  • Pour les besoins modernes — déconseillé.

5. Subtilités utiles

Tableau comparatif des encodages

Encodage Octets par caractère Langues prises en charge Compatibilité avec ASCII Où c’est utilisé
UTF-8
1-4 Toutes Totale Web, Java, JSON, XML, Linux
UTF-16
2 ou 4 Toutes Non Interne à Java, Windows, XML
ISO-8859-1
1 Europe occidentale Totale Anciens programmes, bases, HTTP

Comment choisir un encodage ?

  • UTF-8 — votre choix pour 99 % des cas. Compatible avec ASCII, prend en charge toutes les langues, taille minimale pour un texte anglais, standard pour le Web et Java.
  • UTF-16 — utilisez-le uniquement si la spécification l’exige ou en cas d’intégration avec des applications Windows.
  • ISO-8859-1 — seulement pour la compatibilité avec d’anciens systèmes. Ne l’utilisez jamais pour stocker de la cyrillique, du grec, de l’arabe, etc.

Comment savoir dans quel encodage est un fichier ?

  • Ouvrez le fichier dans un éditeur qui affiche l’encodage (par exemple, Notepad++, VS Code).
  • Si vous voyez des « caractères illisibles », essayez d’ouvrir le fichier avec un autre encodage.
  • Dans un terminal Linux, vous pouvez utiliser la commande file nom_de_fichier — elle indique parfois l’encodage.

Comment définir l’encodage en Java ?

Utilisez les classes du package java.nio.charset :

  • StandardCharsets.UTF_8
  • StandardCharsets.UTF_16
  • StandardCharsets.ISO_8859_1

Ou via le nom de l’encodage :

Charset windows1251 = Charset.forName("Windows-1251");
Charset utf8 = Charset.forName("UTF-8");

6. Pratique : que se passe‑t‑il si vous vous trompez d’encodage ?

Essayons une petite expérience. Nous allons écrire une chaîne en UTF-8, puis tenter de la lire comme ISO-8859-1 :

import java.nio.file.*;
import java.nio.charset.*;

public class EncodingMismatchDemo {
    public static void main(String[] args) throws Exception {
        String text = "Bonjour, le monde !"; // Texte en français

        // Nous écrivons en UTF-8
        Files.write(Paths.get("utf8demo.txt"), text.getBytes(StandardCharsets.UTF_8));

        // Nous lisons en ISO-8859-1 (INCORRECT !)
        String wrong = Files.readString(Paths.get("utf8demo.txt"), StandardCharsets.ISO_8859_1);
        System.out.println("Lecture incorrecte : " + wrong);

        // Maintenant, nous lisons correctement
        String correct = Files.readString(Paths.get("utf8demo.txt"), StandardCharsets.UTF_8);
        System.out.println("Lecture correcte : " + correct);
    }
}

Résultat :

  • Dans le premier cas, vous verrez des caractères illisibles — un ensemble de symboles étranges.
  • Dans le second cas — un texte lisible.

7. Erreurs typiques lors de la gestion des encodages

Erreur n° 1 : lecture d’un fichier avec un encodage incorrect. Si un fichier est enregistré en UTF-8 et que vous le lisez comme ISO-8859-1 ou Windows-1251, alors tous les caractères non ASCII deviendront du « bruit ». C’est un grand classique : « chez moi tout marche, mais chez le collègue — non ».

Erreur n° 2 : tentative d’enregistrer des caractères « étrangers » dans un encodage monooctet. Si vous essayez de sauvegarder de la cyrillique ou des idéogrammes en ISO-8859-1, Java les remplacera par des points d’interrogation ou lèvera une erreur. Les données seront perdues irrémédiablement.

Erreur n° 3 : utilisation de l’encodage système « par défaut ». Dans certaines méthodes Java (par exemple, new FileReader("file.txt")), l’encodage n’est pas spécifié explicitement — c’est l’encodage système qui est utilisé. Sur une machine, il peut s’agir de UTF-8, sur une autre — de Windows-1251, sur une troisième — de quelque chose d’exotique. Utilisez donc toujours des méthodes où l’on peut préciser explicitement l’encodage.

Erreur n° 4 : ouvrir un fichier UTF-16 comme UTF-8. Un fichier enregistré en UTF-16, si on l’ouvre comme UTF-8, contiendra beaucoup de zéros et de symboles étranges, car les octets seront interprétés de manière incorrecte.

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION