Activité : Encodage de caractères et entrée standard

Mise en situation

Vous avez appris qu’il existe plusieurs manières d’encoder des caractères et vous décidez de mener quelques expériences pour vous en rendre compte par vous-même.

Consigne

On vous demande de réaliser les expériences décrites ci-après et de répondre aux questions qui vous sont posées.

Résultat attendu

Un compte rendu de l’activité et les réponses aux questions posées dans une section de votre rapport du module.

Objectifs

À la fin de cette activité, vous devez :

  1. Être capable d’initialiser correctement un objet de type Scanner en Java pour l’utiliser dans la console de Windows (cmd.exe).
  2. Être capable d’expliquer pourquoi on n’initialise pas un objet de type Scanner de la même manière selon que le programme doit être exécuté dans la fenêtre output de NetBeans sous Windows, dans la console de Windows ou sous Linux.

Ressources

Document :

Logiciel :

  • Oracle NetBeans

Mise en route

En Java, pour lire des valeurs que l’utilisateur saisit au clavier, nous utilisons un objet Scanner que nous devons créer de la manière suivante :

1
2
3
4
5
    ...

    Scanner input = new Scanner(System.in);

    ...
Fig. 1 – Construction d’un nouvel objet de type Scanner à l’aide de l’opérateur new

Le constructeur Scanner demande un paramètre de type InputStream. Un objet de type InputStream que l’on peut traduire par « flux d’entrée ». Cet objet permet de lire, l’un après l’autre (séquentiellement) et dans l’ordre, les octets contenu dans un fichier ou en provenance d’un périphérique comme le clavier. L’objet System.in est un objet de type InputStream qui représente flux de l’entrée standard ou stdin du programme. Cette entrée standard est généralement le clavier ou, plus précisément, le terminal (voir « Qu’est-ce qu’un terminal »)

Le rôle d’un objet de type Scanner est de convertir les octets du flux d’entrée en caractères pour obtenir une chaîne de caractères (String). Cette chaîne de caractère peut ensuite être renvoyée par la méthode nextLine() ou interprétée pour être convertie en nombre et renvoyée par les méthodes nextInt() ou nextDouble().

Pour interpréter les caractères du flux d’entrée, un objet de type Scanner doit se référer à une norme d’encodage pour savoir à quel caractère correspond tel octet. Mais à quelle norme se réfère-t-il ?

De même, pour envoyer les octets qui correspondent aux caractères saisis au clavier par l’utilisateur, le terminal (GNOME terminal, cmd.exe ou la fenêtre output de NetBeans) doit se référer à une norme d’encodage pour savoir quels octets envoyer pour chaque caractère saisi. Mais, là encore, quelle est cette norme ?

Pour le découvrir, livrons-nous à quelques expériences.

Expériences

Effectuez les expériences ci-dessous dans l’ordre, en prenant la peine de noter vos observations à la fin de chacune d’elle.

Expérience 1

Avec NetBeans, créez un nouveau projet Java, nommez-le EncodingExperiment1 puis, conformément à la figure 2, renommez le package de la classe principale. Avant de terminer, relevez le chemin de votre projet; vous en aurez besoin plus tard.

Fig. 2 – Création du projet EncodingExperiment1
Fig. 2 – Création du projet EncodingExperiment1

Dans le fichier EncodingExperiment1.java, copiez le code du programme de la figure 3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package ch.epaifribourg.ict.m100;

import java.util.Scanner;

public class EncodingExperiment1 {

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);
        
        System.out.println("Veuillez saisir une ligne de texte avec des accents et des caractères spéciaux : ");
        String text = input.nextLine();

        System.out.println();
        System.out.println("Vous avez saisi la ligne suivante : ");
        System.out.println(text);
    }
}
Fig. 3 – Programme EncodingExperiment1

Exécutez le programme dans NetBeans et saisissez une chaîne de caractère avec des accents et des caractères spéciaux et terminez en appuyant sur la touche Entrer. Utilisez par exemple le texte suivant : Température : 2°C.

Avant de poursuivre, décrivez par écrit ce que vous constatez et formulez, toujours par écrit, une ou plusieurs hypothèses pour expliquer le phénomène.

Expérience 2

Essayons maintenant d’écrire un programme qui affiche non pas la chaîne de caractère mais la valeurs de chaque octet envoyé par le terminal. Pour cela, créer un nouveau projet nommé EncodingExperiment2 et copiez le code du programme de la figure 4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package ch.epaifribourg.ict.m100;

import java.io.IOException;

public class EncodingExperiment2 {

    public static void main(String[] args) throws IOException {
       
        System.out.println("Veuillez saisir une ligne de texte avec des accents et des caractères spéciaux : ");
        
        // Lis l’une après l’autre les valeurs des octets de l’entrée standard 
        // tant que la valeur est différent de de 0x0A.
        int c = System.in.read();
        while (c != 0x0A) {
            System.out.printf("%02X ", c);
            c = System.in.read();
        } 
        
        System.out.println();
    }
}
Fig. 4 – Programme EncodingExperiment2

Exécutez le programme dans NetBeans et saisissez le même texte que pour l’expérience précédente. En utilisant les tables des normes d’encodage de caractères que vous avez dans le diaporama “Encodage de caractères”, déterminez la norme utilisée par la fenêtre output de NetBeans pour coder les caractères.

Expérience 3

Il s’agit cette fois d’exécuter le programme à l’aide de la console de Windows. Pour cela, il faut tout d’abord demander à NetBeans de créer un fichier exécutable .jar en sélectionnant « Clean and Build Project » dans menu « Run » ou en appuyant sur les touches  SHIFT-F11 pour votre projet. Lancez ensuite la console (cmd.exe) et exécutez les commandes suivantes pour vous rendre dans le répertoire de votre projet et exécuter le programme :

1
2
3
D:
CD %userprofile%\documents\NetBeansProjects\EncodingExperiment2
java -jar dist\EncodingExperiment2.jar

À l’invitation de votre programme, tapez une nouvelle fois la même chaîne et utilisez à nouveau les tables du diaporama pour déterminer la norme utilisée par la console de Windows pour coder les caractères.

Expérience 4

Lorsque l’on crée un objet de type Scanner en Java, il est possible de spécifier la norme d’encodage à utiliser pour décoder les caractères en provenance de l’entrée standard (System.in). Pour cela, il suffit de donner au constructeur de l’objet Scanner un deuxième paramètre de type chaîne de caractères (String) qui contient le nom de la norme.

Créez un nouveau projet nommé EncodingExperiment4 et copiez le code de la figure 5.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package ch.epaifribourg.ict.m100;

import java.util.Scanner;

public class EncodingExperiment4 {

    public static void main(String[] args) {
        
        // Remplacer la chaîne vide par le nom de la 
        // norme pour la fenêtre output de NetBeans
        String encoding = ""; 

        Scanner input = new Scanner(System.in, encoding);
        
        System.out.println("Veuillez saisir une ligne de texte avec des accents et des caractères spéciaux : ");
        String text = input.nextLine();

        System.out.println();
        System.out.println("Vous avez saisi la ligne suivante : ");
        System.out.println(text);
    }
}
Fig. 5 – Programme EncodingExperiment4

En utilisant les noms qui se trouve dans la deuxième colonne du tableau des normes d’encodage supportées par Java, remplacez la chaîne vide par le nom de la norme d’encodage que vous avez déterminé à la fin de l’expérience 2. Exécutez le programme dans NetBeans et vérifiez que cela fonctionne.

Expérience 5

Créez un nouveau projet nommé EncodingExperiment5 et copiez le code de la figure 6.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package ch.epaifribourg.ict.m100;

import java.util.Scanner;

public class EncodingExperiment5 {

    public static void main(String[] args) {

        // Remplacez la chaîne vide par le nom de la 
        // norme pour la console de Windows.
        String encoding = ""; 

        Scanner input = new Scanner(System.in, encoding);
        
        System.out.println("Veuillez saisir une ligne de texte avec des accents et des caractères spéciaux : ");
        String text = input.nextLine();
        System.out.println();
        System.out.println("Vous avez saisi la ligne suivante : ");
        System.out.println(text);
    }
}
Fig. 6 – Programme EncodingExperiment5

Lancez votre projet EncodingExperiment5 depuis la console de Windows et vérifiez que cela fonctionne.

Questions

  1. Dans les expériences 2 et 3, pourquoi les codes de caractères n’apparaissent-ils pas au fur et à mesure que vous tapez les caractères, mais d’un seul coup lorsque vous appuyez sur la touche Entrer ?
  2. En Java, on peut déterminer la norme d’encodage qu’un objet de type Scanner à l’aide de la fonction Charset.defaultCharset().displayName()qui renvoie une chaîne de caractère. En utilisant cette fonction, déterminez la norme d’encodage par défaut de Java.
  3. Quelle norme d’encodage doit-on utiliser pour écrire du code en Java ? Utilisez Notepad++ pour vérifier que vos fichiers .java utilisent les bons codes de caractères. Expliquez comment vous vous y prenez.